He encontrado que, el caso 1 y el caso 3 se puede compilar sin errores, pero el caso 2. (SubClassB extiende SuperClassA, que es la clase abstracta) Lo que me pregunto es, ¿por qué casos 1 y 3 no tienen errores de compilación. Si se trata de un error de JDK, ¿por qué el caso 2 no puede pasar la comprobación de reparto?
// case 1
List<SuperClassA> a = new ArrayList<>();
SubClassB b = (SubClassB) a;
// case 2
List<Number> m = new ArrayList<>();
Long n = (Long) m; //Error:(xx,yy) java: incompatible types: java.util.List<java.lang.Number> cannot be converted to java.lang.Long
// case 3
List<Exception> e = new ArrayList<>();
RuntimeException d = (RuntimeException) e;
Tenga en cuenta que el caso 1 y el caso 3 se fallará tanto en tiempo de ejecución.
En tiempo de compilación, el compilador se quejará moldes sobre incompatibles sólo si la especificación de lenguaje lo dice. La especificación de lenguaje permite a los casos 1 y 3 porque no van a 100% fallar.
Caso 1 no será 100% fallar, por lo que se refiere al compilador, ya que piensa que a
puede contener una instancia de cualquier tipo que implementa List<SuperClassA>
. ¿Qué pasa si hay una subclase de SubclassB
que efectivamente en marcha List<SuperClassA>
? ¿Y si a
en realidad contiene una instancia de esa subclase de SubclassB
? A continuación, el molde tendría éxito!
Lo mismo vale para el caso 2. ¿Qué pasa si hay una subclase de RuntimeException
que efectivamente en marcha List<Exception>
? ¿Y si e
en realidad contiene una instancia de esa subclase de RuntimeException
? A continuación, el molde tendría éxito!
Caso 2 muestra un error porque Long
se ofrecen final
. Allí no podía ser una subclase que implementa List<Number>
, por lo que definitivamente va a fallar.
Esto se especifica en §5.5.1 de la especificación (cursiva son los bits correspondientes):
Dado un tiempo de compilación tipo de referencia S (fuente) y un tipo de referencia de tiempo de compilación T (objetivo), existe una conversión de colada de S a T si no se producen errores de tiempo de compilación debido a las siguientes reglas.
...
Si S es un tipo de interfaz:
Si T es un tipo de matriz, entonces S debe ser el tipo
java.io.Serializable
oCloneable
(las únicas interfaces implementadas por arrays), o un tiempo de compilación se produce error.Si T es un tipo de clase o interfaz que no es
final
(§8.1.1), entonces si existe un supertipo X de T, y un supertipo Y de S, de manera que tanto X como Y son tipos parametrizados provably distintas, y que el borraduras de X e y son los mismos, se produce un error de tiempo de compilación.De lo contrario, el reparto es siempre legal en tiempo de compilación (porque incluso si T no implementa S, una subclase de T fuerzas).
Si T es un tipo de clase que es final , a continuación:
- Si S no es un tipo parametrizado o un tipo de prima, entonces T debe implementar S, o se produce un error en tiempo de compilación.