Ce que vous essayez de faire est très utile et je trouve que je dois le faire très souvent dans le code que j'écris. Un exemple de cas d'utilisation:
Disons que nous avons une interface Foo
et que nous avons un zorking
package qui a un ZorkingFooManager
qui crée et gère des instances de package-private ZorkingFoo implements Foo
. (Un scénario très courant.)
Donc, ZorkingFooManager
doit contenir un private Collection<ZorkingFoo> zorkingFoos
mais il doit exposer un fichier public Collection<Foo> getAllFoos()
.
La plupart des programmeurs java ne réfléchiraient pas à deux fois avant de l'implémenter getAllFoos()
en allouant un nouveau ArrayList<Foo>
, en le remplissant avec tous les éléments zorkingFoos
et en le renvoyant. J'apprécie l'idée qu'environ 30% de tous les cycles d'horloge consommés par le code java s'exécutant sur des millions de machines partout dans le monde ne font rien d'autre que créer des copies inutiles de ArrayLists qui sont récupérées en microsecondes après leur création.
La solution à ce problème est, bien entendu, de réduire la collection. Voici la meilleure façon de le faire:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Ce qui nous amène à la castList()
fonction:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
La result
variable intermédiaire est nécessaire en raison d'une perversion du langage java:
return (List<T>)list;
produit une exception "cast non vérifié"; jusqu'ici tout va bien; mais alors:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
est une utilisation illégale de l'annotation suppress-warnings.
Ainsi, même s'il n'est pas casher à utiliser @SuppressWarnings
sur une return
instruction, il est apparemment bien de l'utiliser sur une affectation, donc la variable supplémentaire "result" résout ce problème. (Il devrait être optimisé par le compilateur ou par le JIT de toute façon.)