Quello che stai cercando di fare è molto utile e trovo che devo farlo molto spesso nel codice che scrivo. Un esempio di utilizzo:
Supponiamo che abbiamo un'interfaccia Foo
e abbiamo un zorking
pacchetto che ha un pacchetto ZorkingFooManager
che crea e gestisce istanze di pacchetto-private ZorkingFoo implements Foo
. (Uno scenario molto comune.)
Quindi, ZorkingFooManager
deve contenere un private Collection<ZorkingFoo> zorkingFoos
ma deve esporre a public Collection<Foo> getAllFoos()
.
La maggior parte dei programmatori Java non ci penserebbe due volte prima di implementare getAllFoos()
come allocare un nuovo ArrayList<Foo>
, popolarlo con tutti gli elementi zorkingFoos
e restituirlo. Mi piace intrattenere l'idea che circa il 30% di tutti i cicli di clock consumati dal codice Java in esecuzione su milioni di macchine in tutto il pianeta non stiano facendo altro che creare copie così inutili di ArrayList che sono microsecondi raccolti dalla spazzatura dopo la loro creazione.
La soluzione a questo problema è, ovviamente, il down-casting della raccolta. Ecco il modo migliore per farlo:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Il che ci porta alla castList()
funzione:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
La result
variabile intermedia è necessaria a causa di una perversione del linguaggio java:
return (List<T>)list;
produce un'eccezione "non selezionata"; Fin qui tutto bene; ma allora:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
è un uso illegale dell'annotazione degli avvisi di soppressione.
Quindi, anche se non è kosher da usare @SuppressWarnings
su return
un'istruzione, è apparentemente bene usarlo su un compito, quindi la variabile "risultato" extra risolve questo problema. (Dovrebbe essere comunque ottimizzato dal compilatore o dalla JIT.)