2011-10-14 9 views
11

Vamos a tener la siguiente jerarquía de clases:¿Error genérico de Java?

public class MyType { 
} 

public class MySuperclass<T extends MyType> { 
    protected Map<String, String> myMap = new TreeMap<String, String>(); 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

public class MySubclass extends MySuperclass { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); // <-- compilation error 
    } 
} 

¿Por qué hay un error de compilación en el método de overriden MySubclass? El mensaje de error es "No coinciden los tipos: no se puede convertir de Objeto a Cadena".

Lo interesante es que desaparece el error de compilación si defino genéricos tipo de clase de MySuperclass en MySubclass definición:

public class MySubclass extends MySuperclass<MyType> { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

Puede alguien explicar este comportamiento? Lo consideraría un error del compilador de Java.

Estoy usando jdk1.6.0_24.

Respuesta

12

No es un error. Al extender MySuperclass en lugar de MySuperclass<MyType>, que está ampliando el tipo de prima MySuperclass, lo que significa que myMap también será de tipo Map en lugar de Map<String, String>.

+1

exactamente. Ese fue uno de los "rompecabezas" de Bloch. – Bozho

+0

¿Entonces los genéricos son todo o nada? Si usa un tipo sin procesar, no obtendrá ningún genérico para ese tipo, ni siquiera las partes que no dependen de 'T' en absoluto? – Thilo

+2

Pero, ¿qué tiene la definición genérica de 'MySuperclass ** **' en común con los genéricos de 'Map ** ** myMap'? Esas son dos definiciones de genéricos diferentes sin ninguna 'conexión' entre ellas. No lo entiendo –

1

De hecho no es razonable. Esto se puede considerar un error en el diseño. La causa principal es la decisión de mantener la API de compilación generizada compatible con versiones anteriores, en lugar de mantener intacta la anterior e introducir una nueva API generada. Esta decisión es técnicamente absurda, y sus explicaciones son irrisorias. La verdadera razón detrás de esto es que probablemente Sun se vio obligado a expulsar Java5 pero no tenía recursos suficientes, por lo que tomaron la ruta fácil (borrado). Así que aquí estamos, totalmente jodidos. Este sistema de tipo bastardo no solo es un problema en sí mismo, también es un gran obstáculo para la introducción de cualquier característica nueva.

Cuestiones relacionadas