2011. augusztus 15., hétfő

Collections.emptyList() és a generikus típuskényszerítés

Sajnos mostanában nem jut annyi időm blogolásra, mint szeretném, és ez a bejegyzés is mindössze egy szösszenet lesz.
A Collections osztály, mint nevéből is következik, a Collection példányok manipulálására, és előre definiált Collection-ök hozzáféréséhez nyújt kényelmes eszközt. Az osztály részleteibe nem szeretnék belemenni, ezt az olvasóra bízom. Kiszemelt áldozatom az emptyList metódus. A metódus forrását megnézve láthatjuk, hogy nem csinál egyebet, mint az osztályban statikus paraméterként deklarált nyers típusú EMPTY_LIST-et adja vissza a kívánt típusra alakítva. Természetesen ez a lista egy változtathatatlan lista, tehát elemeket ebbe nem tudunk tenni. Használata végtelenül egyszerű.
List<String> stringList = Collections.emptyList();
A fordító megpróbálja kitalálni, hogy milyen típusra kell alakítani az EMPTY_LIST példányt, teszi ezt úgy, hogy megnézi milyen típusba szeretnénk belepasszírozni a listát. Az esetek többségében sikerül is ez a művelet, ám mit tehetünk a következő esetben:
public static void bar() {
        foo(Collections.emptyList());
    }
    
    public static void foo(List<String> stringList) {}
Már az IDE is jelzi, hogy ez így nem lesz jó, nem tudja megállapítani milyen típusra kell alakítani a listát. Netbeans fel is ajánlja, hogy létrehoz egy foo(List<Object> stringList) metódust, de mi ezt nem szeretnénk. Egyik lehetőségünk, hogy a paramétert egy lokális változóba kimozgatjuk, és a helyes típussal adjuk át a metódusnak. Ez a megoldás célra vezető, viszont feleslegesen növeli kódunk méretét. A következő eshetőség, hogy a nyers EMPTY_LIST-et adjuk át paraméterként, viszont így hazavágjuk a típusbiztonságot. Nyers típusoknál a JVM egyszerűen levágja a típusellenőrzést. Ennek oka a visszafelé kompatibilitás, a generikusok megjelenése óta nem javallott a nyers típusok használata. Az elegáns megoldás egyszerű, segítsük a fordítót, és mondjuk meg neki milyen típusra alakítsa a listát.
foo(Collections.<String>emptyList());
Az itt említett módszer nem a Collections osztály sajátossága, alkalmazható minden generikus metódusra. Választásom azért esett erre az osztályra, mert ezt eléggé gyakran használja mindenki , aki Java-ban programozik, és része a Java SE-nek.

2 megjegyzés:

  1. Mindig tanul az ember valami újat a legegyszerűbb osztályok esetén is. Bravó!

    VálaszTörlés
  2. Kicsit utánnaolvastam a dolognak (Effective Java 5.28), és a könyv valamiért azt írja, hogy ez nem elegáns megoldás. Szeméy szerint ezzel nem értek egyet, miért ne segítsük a fordítót egy lépésben ahelyett, hogy trükközünk a típusokkal.

    VálaszTörlés