ejemplo - text box java
¿Por qué Java te permite lanzar a una colección? (3)
El compilador no impide que el código lance un tipo a una interfaz, a menos que pueda establecer con seguridad que la relación es imposible.
Si el tipo de destino es una interfaz, entonces tiene sentido porque una clase que extiende
Foo
puede implementar
Map<String, String>
.
Sin embargo, ten en cuenta que esto solo funciona ya que
Foo
no es
final
.
Si declaraste tu clase con
final class Foo
, ese lanzamiento no funcionaría.
Si el tipo de destino es una clase, en este caso simplemente fallará (pruebe
(HashMap<String, String>) this
), porque el compilador sabe con certeza que la relación entre
Foo
y
HashMap
es imposible.
Para referencia, estas reglas se describen en
JLS-5.5.1
(T = tipo de destino -
Map<String, String>
, S = tipo de fuente -
Foo
)
Si T [tipo de destino] es un tipo de interfaz:
Si S no es una clase final (§8.1.1), entonces, si existe un supertipo X de T y un supertipo Y de S, tal que tanto X como Y sean tipos parametrizados claramente distintos, y que los borrados de X e Y son lo mismo, se produce un error en tiempo de compilación.
De lo contrario, la conversión siempre es legal en tiempo de compilación (porque incluso si S no implementa T, una subclase de S podría).Si S es una clase final (§8.1.1), S debe implementar T, o se produce un error en tiempo de compilación.
Tenga en cuenta el comentario en negrita y cursiva en el texto citado.
Esta pregunta ya tiene una respuesta aquí:
- Java casting en interfaces 4 respuestas
Tengo una clase
foo
simple y puedo convertir a una interfaz de colección (
Map
o
List
) sin ningún error de compilación.
Tenga en cuenta que la clase
Foo
no implementa ninguna interfaz ni amplía ninguna otra clase.
public class Foo {
public List<String> getCollectionCast() {
return (List<String>) this; // No compiler error
}
public Map<String, String> getCollection2Cast() {
return (Map<String, String>) this; // No compiler error
}
public Other getCast() {
return (Other)this; // Incompatible types. Cannot cast Foo to Other
}
public static class Other {
// Just for casting demo
}
}
¿Por qué el compilador de Java no devuelve
error de tipos incompatibles
cuando intento convertir la clase
Foo
en una colección?
Foo
no implementa la
Collection
.
Esperaría un error de tipos incompatibles, ya que, dada la firma de la clase
Foo
actual, esto no puede ser una
Collection
.
No es porque sean clases de colección, es porque son
interfaces
.
Foo
no los implementa, pero las subclases podrían hacerlo.
Entonces, no es un error en tiempo de compilación, ya que esos métodos pueden ser válidos para las subclases.
En
tiempo de ejecución
, si
this
no es de una clase que implementa esas interfaces, naturalmente es un error de tiempo de ejecución.
Si cambia la
List<String>
a
ArrayList<String>
, también obtendrá un error en el compilador, ya que una subclase de
Foo
podría implementar la
List
, pero no puede extender
ArrayList
(ya que
Foo
no).
De manera similar, si logra que
Foo
final
, el compilador le dará un error para sus cambios de interfaz porque sabe que nunca pueden ser ciertos (ya que
Foo
no puede tener subclases y no implementa esas interfaces).
https://docs.oracle.com/javase/8/docs/api/java/util/List.html
Todas las superinterfaces: colección, iterable
Foo es una lista es una colección.