Generics Egyszerűbb példák (java.util csomagból): public interface List<E> { void add(e x); Iterator<E> iterator(); public interface Iterator<E> { E next(); boolean hasnext(); E - formális típusparaméter, amely aktuális értéket a kiértékelésnél vesz fel (pl. Integer, etc.). Altípusosság Nem konvertálhatók, ennek oka: List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error // Mert akkor lehetne ilyet csinalni: l2.add(new Object()); l1.get(0); // Hiba: Object -> String castolas Wildcardok Probléma: általános megoldást szeretnénk, amely minden collectiont elfogad, függetlenül az azokban tárolt elemektől (pl. ki szeretnénk őket írni). Collection<Object> nem őse. Ha nem használunk genericeket, megoldható, viszont warningot generál: void print(collection c) { for (Object o : c) System.out.println(o); A megoldás a wildcard használata: Collection<?> minden kollekcióra ráillik. Ilyenkor Object-ként hivatkozhatunk az elemekre: 1
void print(collection<?> c) { for (Object o : c) System.out.println(o); Vigyázat! A?!= Object! Csak egy ismeretlen típust jelent. kódrészlet is fordítási hibához vezet: Így a következő List<?> c =...; l.add(new Object()); // forditasi hiba Nem tudjuk, hogy mi van benne, lekérdezni viszont lehet (mert tudjuk, hogy minden objektum az Object leszármazottja). Bounded wildcard Amikor tudjuk, hogy adott helyen csak adott osztály leszármazottai szerepelhetnek, első (rossz) megközelítés: abstract class Super { class Sub1 extends Super { class Sub2 extends Super {... void func(list<super> l) {... // Rossz! Probléma: func() csak List<Super> paraméterrel hívható meg, List<Sub1>, List<Sub2> nem lehet paramétere (nem altípus). Megoldás: bounded wildcard: void func(list<? extends Super> l) {... Belepakolni ugyanúgy nem tudunk, mint a? esetén, azaz erre fordítási hibát kapunk: void func(list<? extends Super> l) { l.add(new Sub1()); // hiba Felfelé is megköthető a wildcard a <? super T> jelöléssel. (The syntax? super T denotes an unknown type that is a supertype of T) 2
Generikus osztályok, függvények Osztálydefinícióban bevezethető típusparaméter az osztályhoz, ez minden member-nél használható. Példa: package generics; public class Pair<T, S> { private final T first; private final S second; public Pair(final T first, final S second) { super(); this.first = first; this.second = second; public T getfirst() { return first; public S getsecond() { return second; // Esetleges null ellenorzeseket tessek elvegezni! // Itt az attekinthetoseg kedveert ettol eltekintettem. public boolean equals(final Object obj) { if (obj instanceof Pair) { Pair<?,?> pair = (Pair<?,?>) obj; return first.equals( pair.first ) && second.equals( pair.second ); return false; // Esetleges null ellenorzeseket tessek elvegezni! // Itt az attekinthetoseg kedveert ettol eltekintettem. public int hashcode() { return first.hashcode() + second.hashcode(); public String tostring() { return "(" + first + ", " + second + ")"; 3
Generikus függvények esetén szintén a definícióban használható. Példa: package generics; public class ArrayUtils { public static final <T, S extends T> boolean isin(final T[] arr, final S element) { for (final T t : arr) { if (t.equals(element)) return true; return false; public static void main(final String[] args) { final String[] sarr = {"a", "b", "c"; System.out.println( isin(sarr, "c") ); +/- Feladatok Készíts egy saját, generikus Stack implementációt! A reprezentációt tetszőlegesen megválaszthatod. Valósítsd meg a szokásos stack muveleteket: push(e), pop(), top(), size(), isfull(), isempty(). Gyakorló feladatok 1. Feladat Készíts egy generikus reverse() függvényt, amely egy tetszőleges lista adatszerkezetet képes visszafelé kiírni a képernyőre! 2. Feladat Készíts egy generikus fill() függvényt, amely a paraméterként kapott, tetszőleges lista minden elemét lecseréli a megadott elemre. 4
3. Feladat Készíts egy olyan generikus min() és max() függvényt, amely egy tetszőleges kollekcióban megkeresi és visszaadja a minimális és maximális elemet! Segítség: kell hozzá a Comparable! public static <T extends Comparable<? super T>> T max(collection<t> coll) További magyarázat ehez: http://docs.oracle.com/javase/tutorial/extra/generics/morefun.html 5