To, co próbujesz zrobić, jest bardzo przydatne i uważam, że muszę to robić bardzo często w kodzie, który piszę. Przykład użycia:
Powiedzmy, że mamy interfejs Foo
i mamy zorking
pakiet, ZorkingFooManager
który tworzy i zarządza wystąpieniami pakietu private ZorkingFoo implements Foo
. (Bardzo powszechny scenariusz.)
Więc ZorkingFooManager
musi zawierać, private Collection<ZorkingFoo> zorkingFoos
ale musi ujawniać public Collection<Foo> getAllFoos()
.
Większość programistów Java nie zastanowiłaby się dwa razy, zanim zaimplementowałaby getAllFoos()
alokację nowego ArrayList<Foo>
, zapełniając go wszystkimi elementami z zorkingFoos
i zwracając. Cieszy mnie myśl, że około 30% wszystkich cykli zegara zużywanych przez kod Java działający na milionach maszyn na całym świecie nie robi nic poza tworzeniem bezużytecznych kopii ArrayLists, które są zbierane w mikrosekundach po ich utworzeniu.
Rozwiązaniem tego problemu jest oczywiście zdegradowanie kolekcji. Oto najlepszy sposób, aby to zrobić:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Co prowadzi nas do castList()
funkcji:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
result
Zmienna pośrednia jest konieczna ze względu na wypaczenie języka Java:
return (List<T>)list;
tworzy wyjątek „niezaznaczone rzutowanie”; na razie w porządku; ale wtedy:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
jest nielegalnym użyciem adnotacji z ostrzeżeniami.
Tak więc, nawet jeśli użycie @SuppressWarnings
w return
instrukcji nie jest koszerne , najwyraźniej można go używać w przypisaniu, więc dodatkowa zmienna „result” rozwiązuje ten problem. (W każdym razie powinien być zoptymalizowany przez kompilator lub przez JIT).