tutorial ejemplo java collections interface casting

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í:

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).