2010-11-10 8 views
6

Tenemos una jerarquía de clases similar a éste:Sun JDK 1.5 no puede eliminar la referencia de error con genéricos

public class TestDereference { 
private static MainInterface mi = new MainInterfaceImpl(); 

public static void main(String[] args) { 
    System.out.println(mi.getSubInterface().getField()); 
} 
} 

interface MainInterface { 
<T extends SubInterface> T getSubInterface(); 
} 

interface SubInterface { 
Field getField(); 
} 

class Field { 
@Override 
public String toString() { 
    return "Hooray!"; 
} 
} 

class SubInterfaceImpl implements SubInterface { 
Field f = new Field(); 

public Field getField() { 
    return f; 
} 

} 

class MainInterfaceImpl implements MainInterface { 
SubInterfaceImpl si = new SubInterfaceImpl(); 

public <T extends SubInterface> T getSubInterface() { 
    return (T) si; 
} 
} 

Las interfaces en realidad tienen más de una aplicación pero ese no es el problema. Compilar esto con el compilador de Eclipse o Java 1.6 funciona bien (como se ve en ideone). Pero si intento compilar esto con Java 1.5 (que es uno de los requisitos de nuestro proyecto) da el siguiente error:

TestDereference.java:12: test.SubInterface cannot be dereferenced 
       System.out.println(mi.getSubInterface().getField()); 
                ^

También tenga en cuenta que esto no sucede con JDK 1.6 utilizando -target 1.5 o bien, sólo que con JDK 1.5

los únicos casos en los que se produce este error que he encontrado en la web están relacionados con hacer cosas como esta:

double d = 2.0; 
d.toString(); 

donde es evidente cuál es el problema.

Pero en mi caso debería funcionar, ya que está claro que getSubInterface() devuelve una clase de implementación SubInterface que definitivamente tiene el método getField().

¿Es esto un error del compilador? Y qué opciones tengo además de hacer mi.<SubInterface>getSubInterface() cada vez (lo cual funciona, pero como Eclipse no lo marca como un error, la mayoría de las personas en el equipo lo olvidan, y la mayoría usa solo JDK 1.6 para que no lo hagan). nótelo al compilar con línea maven/cmd tampoco)

+0

Qué versiones del JDK exacta está usando? (5 y 6?) –

+0

1.5.0_22 y 1.6.0_20 (según 'javac -version') –

+0

¿Qué sucede cuando prueba el indicador de compilación' -source 1.5' o si establece el nivel de cumplimiento del compilador de Eclipse en 1.5 en lugar de 1.6? –

Respuesta

1

comprobación de error: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5003431

Opción uno:

SubInterface si = mi.getSubInterface(); 
si.getField(); 

Opción dos:

mi.<SubInterface>getSubInterface().getField() 
+0

Así que supongo que si me quedo con 1.5 no hay mucho que pueda hacer aparte de estas dos opciones. Esperaba algo un poco más elegante, supongo, pero esto tendrá que hacer. –

+0

Acepté su respuesta por dar también el enlace al informe de error, que mostraba que solo se había solucionado en 1.6 –

1

Supongo que este es un error que se solucionó en Java6.

volver a escribir el método principal de la siguiente hará que las cosas funcionan tanto en Java5 y 6:

public static void main(String[] args) { 
    SubInterface subInterface = mi.getSubInterface(); 
    System.out.println(subInterface.getField()); 
} 

Parece Java5 necesita la asignación para derivar adecuadamente el tipo T, a pesar de que ya ha declarado que se extiende SubInterface. Java6 maneja esto correctamente y no necesita la asignación adicional.

Cuestiones relacionadas