O que você está tentando fazer é muito útil e acho que preciso fazê-lo com muita frequência no código que escrevo. Um exemplo de caso de uso:
Digamos que temos uma interface Foo
e que temos um zorking
pacote ZorkingFooManager
que cria e gerencia instâncias do pacote-privado ZorkingFoo implements Foo
. (Um cenário muito comum.)
Portanto, ZorkingFooManager
precisa conter um, private Collection<ZorkingFoo> zorkingFoos
mas precisa expor a public Collection<Foo> getAllFoos()
.
A maioria dos programadores de Java não pensaria duas vezes antes de implementar getAllFoos()
como alocar um novo ArrayList<Foo>
, preenchê-lo com todos os elementos zorkingFoos
e retorná-lo. Gosto de pensar que cerca de 30% de todos os ciclos de relógio consumidos pelo código java executado em milhões de máquinas em todo o planeta não fazem nada além de criar cópias inúteis de ArrayLists que são microssegundos após a criação.
A solução para esse problema é, obviamente, fazer o downcast da coleção. Aqui está a melhor maneira de fazer isso:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
O que nos leva à castList()
função:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
A result
variável intermediária é necessária devido a uma perversão da linguagem java:
return (List<T>)list;
produz uma exceção "elenco não verificado"; Por enquanto, tudo bem; mas então:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
é um uso ilegal da anotação de suprimir avisos.
Portanto, mesmo que não seja kosher usar @SuppressWarnings
em uma return
declaração, aparentemente é bom usá-la em uma atribuição, portanto a variável extra "resultado" resolve esse problema. (Deve ser otimizado para fora pelo compilador ou pelo JIT de qualquer maneira.)