(według: https://docs.oracle.com/javase/tutorial/java/generics) Java Wykład Typy generyczne (Generics) (według: https://docs.oracle.com/javase/tutorial/java/generics) Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Typy generyczne (od Java SE 5) Wykład Typy generyczne (od Java SE 5) Typy generyczne umożliwiają definiowanie nowych klas, interfejsów lub metod z wykorzystaniem parametrów, a nie konkretnych typów. W ten sposób możliwe jest wykorzystanie tego samego kodu w różnym kontekście. Główne zalety stosowanie typów generycznych: Efektywniejsze wykrywanie błędów na etapie kompilacji. Brak konieczności rzutowania przy pracy na kolekcjach: ArrayList lista1 = new ArrayList(); lista1.add(new Integer(0)); Integer x = (Integer)lista1.get(0); ArrayList<Integer> lista2 = new ArrayList(); lista2.add(new Integer(0)); Integer x = lista2.get(0); - Możliwość implementacji własnych uniwersalnych algorytmów, które można zastosować do różnych typów. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Typy generyczne - przykład Przykład klasy: class Pudelko { Java Wykład Typy generyczne - przykład Przykład klasy: class Pudelko { private Object obiekt; public void set(Object obiekt) {this.obiekt = obiekt; } public Object get() {return obiekt;} } Wersja generyczna klasy Pudelko: class Pudelko<T> private T obiekt; public void set(T obiekt) {this.obiekt = obiekt; } public T get() {return obiekt;} Tworzenie referencji i obiektu typu generycznego: Pudelko<String> p = new Pudelko<String>(); Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Zapis diamentowy – wnioskowanie typu Java Wykład Zapis diamentowy – wnioskowanie typu Od wersji Java SE 7 można wywołać konstruktor typu generycznego bez podania argumentu typu (o ile kompilator potrafi wywnioskować typ). Wystarczy wtedy użyć notacji „<>”. Pudelko<String> p = new Pudelko<>(); Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Więcej parametrów typu interface Pair<S, T> { Java Wykład Więcej parametrów typu interface Pair<S, T> { public S getFirst(); public T getSecond(); } class MyPair<S, T> implements Pair<S,T> private S first; private T second; public MyPair(S first, T second) this.first = first; this.second = second; public S getFirst() {return first;} public V getSecond() {return second;} Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Przykłady instancji klasy MyPair Java Wykład Przykłady instancji klasy MyPair MyPair<Integer, String> p = new MyPair<Integer, String>(0,”xyz”); MyPair<Integer, String> q = new MyPair<>(0,”xyz”); MyPair<Boolean, Pudelko<Integer>> v = new MyPair<>(true, new Pudelko<Integer>()); Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Typy surowe (Raw types) Java Wykład Typy surowe (Raw types) Używanie typów surowych polega na tworzeniu klas bądź interfejsów na podstawie typów generycznych, ale bez podania argumentu typu. class Pudelko<T> { private T obiekt; public void set(T obiekt) {this.obiekt = obiekt; } public T get() {return obiekt;} } Obiekty typu Pudelko<T> Pudelko<String> p = new Pudelko<>(); Pudelko q = new Pudelko(); //typ surowy Typ Pudelko jest typem surowym dla typu Pudelko<T>. Stosowanie surowych typów jest udostępnione ze względu na wsteczną kompatybilność z klasami z wcześniejszych wersji Javy. Stosowanie surowych typów nie jest zalecane. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
public static <S, T> Java Wykład Metody generyczne Metody generyczne są metodami, które stosują własne parametry typów. Mechanizm jest analogiczny do typów generycznych, z tą różnicą, że parametry typu wprowadzone przez metodę mogą być stosowanie jedynie w ciele tej metody. public class Test { public static <S, T> boolean compare(MyPair<S, T> p1, MyPair<S, T> p2) return p1.getFirst().equals(p2.getFirst()) && p1.getSecond().equals(p2.getSecond()); } Użycie klasy Test MyPair<Integer, String> p = new MyPair<Integer, String>(0,”xyz”); MyPair<Integer, String> q = new MyPair<>(0,”xyz”); boolean is1 = Test.<Integer, String>compare(p, q); boolean is2 = Test.compare(p, q); Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Ograniczone parametry typów Java Wykład Ograniczone parametry typów Definiując typ generyczny, można wprowadzić ograniczenia co do wartości typów w miejsce parametrów. W metodach: public <T extends Integer> void doIt(T t) { ... } W klasach lub interfejsach: class Test <T extends MyClass> Wielokrotne ograniczenia: class K <T extends A & B & C> W ograniczeniach klasa występuje jako pierwsza! Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Zastosowanie ograniczonych parametrów Bez ograniczeń Java Wykład Zastosowanie ograniczonych parametrów Bez ograniczeń public static <T> int ileWiekszych(T[] tab, T elem) { int ile = 0; for (T v: tab) if (v > elem) ++ile;//błąd kompilacji, dlaczego? } return ile; Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Dziedziczenie i podtypy Java Wykład Dziedziczenie i podtypy Przypisanie obiektu do referencji typu nadklasy Object o = new Object(); Integer i = new Integer(9); o = i; //OK public void metoda(Object o) {…} metoda(new String(”Test”)); //OK Dla typów generycznych: public void test(Pudelko<Number> n) {…} test(new Pudelko<Integer>()); //Błąd kompilacji! Uwaga! Dla dowolnych typów A i B typy generyczne MyType<A> i MyType<B> nie mają ze sobą nic wspólnego (nawet w przypadku, gdy B dziedziczy z A). Wspólną klasą bazową dla klas MyType<A> i MyType<B> jest jedynie klasa Object. Można tworzyć hierarchię z typami generycznymi poprzez extends lub implements. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Zastosowanie ograniczonych parametrów Z ograniczeniem: Java Wykład Zastosowanie ograniczonych parametrów Z ograniczeniem: public interface Comparable<T> { public int compareTo(T o); } public static <T extends Comparable<T>> int ileWiekszych(T[] tab, T elem) int ile = 0; for (T v: tab) if (v.compareTo(elem)) ++ile; return ile; Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
Dziękuję za uwagę! Java Wykład Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ