Los genéricos están diseñados a sabiendas para una comprobación de tipos más fuerte en tiempo de compilación. Sin embargo, mientras estudiaba el tutorial oficial de Java, me encontré con esto:
However, in some cases the compiler knows that a type parameter is always valid and allows the cast. For example:
List<String> l1 = ...;
ArrayList<String> l2 = (ArrayList<String>)l1; // OK
de http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCast.
He probado y probado esto (que refleja completamente la documentación):
List<String> l1 = new LinkedList<String>();
ArrayList<String> l2 = (ArrayList<String>)l1; // OK
Aunque todo es bastante explícito (ninguna asignación a un Object
variable, sin wilcarding, etc.), el compilador no puede predecir el error de tiempo de ejecución que aparece después:
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedList cannot be cast to java.util.ArrayList
100% desconcertado.
Respuestas
1 para la respuesta № 1Vuelva a leer el enlace. No está indicando que pueda lanzar un LinkedList
a una ArrayList
. Es decir que puedes alicaído un List
de String
al tipo (probablemente conocido como programador) de ArrayList
de String
. Lo que están tratando de ilustrar es la diferencia entre el genérico tipo de parámetros. Su primer ejemplo muestra el casting de una colección de Integer
a una colección de Number
, lo cual no está permitido.
Normalmente, no se puede convertir a un tipo parametrizado a menos que sea parametrizado por comodines ilimitados. Por ejemplo:
List li = new ArrayList <> (); Lista ln = (Lista) li; // error en tiempo de compilación
Sin embargo, en algunos casos el compilador sabe que un parámetro de tipo siempre es válido y permite la emitir. Por ejemplo:
Lista l1 = ...; ArrayList l2 = (ArrayList) l1; // OKAY