Lo que está tratando de hacer es muy útil y creo que necesito hacerlo muy a menudo en el código que escribo. Un ejemplo de caso de uso:
Digamos que tenemos una interfaz Foo
y tenemos un zorking
paquete ZorkingFooManager
que crea y administra instancias de paquetes privados ZorkingFoo implements Foo
. (Un escenario muy común).
Entonces, ZorkingFooManager
necesita contener a private Collection<ZorkingFoo> zorkingFoos
pero necesita exponer a public Collection<Foo> getAllFoos()
.
La mayoría de los programadores de Java no pensarían dos veces antes de implementar getAllFoos()
como asignar un nuevo ArrayList<Foo>
, rellenarlo con todos los elementos zorkingFoos
y devolverlo. Me gusta entretener la idea de que aproximadamente el 30% de todos los ciclos de reloj consumidos por el código Java que se ejecuta en millones de máquinas en todo el planeta no hace más que crear copias inútiles de ArrayLists que son microsegundos recolectados de basura después de su creación.
La solución a este problema es, por supuesto, reducir la colección. Aquí está la mejor manera de hacerlo:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Lo que nos lleva a la castList()
función:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
La result
variable intermedia es necesaria debido a una perversión del lenguaje java:
return (List<T>)list;
produce una excepción de "lanzamiento no verificado"; Hasta aquí todo bien; pero entonces:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
es un uso ilegal de la anotación suprimir advertencias.
Entonces, aunque no es kosher usarlo @SuppressWarnings
en una return
declaración, aparentemente está bien usarlo en una tarea, por lo que la variable adicional "resultado" resuelve este problema. (De todos modos, debe ser optimizado por el compilador o por el JIT).