Skoro mamy oznaczone, że lista będzie jakiegoś typu ArrayList<e> i zwracany jest też z <e> to na cholerę jeszcze po static to dajemy?
Dajemy <E> bo to jest metoda generyczna, więc przed nazwą funkcji stoją dwa elementy - jeden to generyczne typy użyte w sygnaturze funkcji, drugi to typ zwracany. Oprócz metod generycznych są klasy generyczne i tam generyczne typy podajesz po nazwie klasy (klasa nie ma typu zwracanego, więc nie ma elementu opisującego tenże typ).
Podany typ generyczny nie musi też występować w typie zwracanym. Może być np metoda generyczna typu:
<T extends Number> void showNumber(T number) { ... }
@Wibowit można z tym żyć? Jak to?
Można żyć, bo taki zapis generuje jedynie ostrzeżenie kompilatora. W Javie jest wymazywanie typów (ang. type erasure). Oznacza to, że po kompilacji typy generyczne są wymazywane i istnieje tylko jedna instancja każdej klasy (zamiast różnych instancji dla różnych parametryzacji). Z drugiej strony kompilator automatycznie wrzuca odpowiednie rzutowania, więc przy błędnym użyciu generyków dostaniemy ClassCastException. Klasa typu class X<E>
po wymazywaniu typów będzie wyglądać tak: class X
. Czyli np new HashMap<K, V>
będzie zamienione na new HashMap
, z tym, że w odpowiednich miejscach w kodzie będą wstawione rzutowania (na etapie kompilacji). Wymazywanie można zrobić ręcznie
przypisując surowy typ do typu sparametryzowanego. Wygeneruje to jednak ostrzeżenie kompilatora - przy dodaniu odpowiedniej flagi (Xlint:unchecked czy jakoś tak) kompilator zacznie więcej mówić nt sprawy. Przy braku unchecked warnings w naszym kodzie możemy być w zasadzie pewni, że nie dostaniemy ClassCastException w naszym kodzie podczas używania generyków. Jeśli jednak zastosujemy błędne konstrukcje to kompilator już takiej gwarancji nie może dać. Z tego względu warto unikać unchecked warnings, by nie narażać się niepotrzebnie na strzał w stopę.
W pewnym sensie, jeżeli pomniemy parametryzację klasy generycznej to jest to tożsame z wstawieniem Object
jako typów. Jednak tylko w pewnym sensie, bo kompilator nie sprawdza kowariancji, inwariancji, etc (uporządkowania typów: https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) )