varios reconoce proyecto programa interno externo ejecutar desde consola compile compilar como comando archivos java generics collections java-7 java-6

reconoce - La clase genérica se compila en Java 6, pero no en Java 7



compile java command line linux (2)

Tengo una interfaz en Java 6 que compila correctamente:

public interface IMultiMap<K, V> extends Map<K, Set<V>> { public int valueSize(); public boolean put(K key, V value); public void clear(Object key); public boolean isEmpty(Object key); }

Pero en Java 7, esta interfaz no compila. Recibo un error de compilación en el valor boolean put(K, V) que tiene el mismo borrado que V put(K, V) . El error completo del compilador:

error: name clash: put(K#1,V#1) in IMultiMap and put(K#2,V#2) in Map have the same erasure, yet neither overrides the other public boolean put(K key, V value); where K#1,V#1,K#2,V#2 are type-variables: K#1 extends Object declared in interface IMultiMap V#1 extends Object declared in interface IMultiMap K#2 extends Object declared in interface Map V#2 extends Object declared in interface Map

Para el registro, agregar cualquier tipo de anulación no funciona. He intentado anular explícitamente Map.put , pero el error sigue apareciendo. Cambiar el tipo de retorno de mi put es discutible ya que este error está bloqueando el error potencial que se puede alcanzar, y si este error se solucionara, los dos métodos no tendrían el mismo nombre / firma de parámetros de todos modos.

Creo que podría intentar reflexionar sobre Java 6 y ver cómo terminan los tipos de parámetros reales en el código de bytes compilado de Java 6. Está claro que ambos métodos de Java 7 se están borrando para put(Object, Object) . Publicaré los resultados de la reflexión aquí una vez que lo haga.

Mientras tanto, mi solución temporal será simplemente cambiar el nombre de put a putSingle , pero ¿es correcto este nuevo comportamiento? ¿Cambió alguna parte de las especificaciones de genéricos para Java 7 que hace que el antiguo comportamiento de Java 6 sea incorrecto? ¿O es esto un error en el compilador de Java 7?

Gracias por adelantado.

EDITAR: Corrí el código de reflexión. Echa un vistazo a mi respuesta a continuación.


Creo que es un error en 1.6 que se corrigió en 1.7. Extracto de esta página :

Sinopsis: una clase no puede definir dos métodos con la misma firma borrada pero dos tipos de devolución diferentes
Descripción: una clase no puede definir dos métodos con la misma firma borrada, independientemente de si los tipos de devolución son iguales o no. Esto se deduce de JLS, Java SE 7 Edition, sección 8.4.8.3. El compilador JDK 6 permite métodos con la misma firma borrada pero diferentes tipos de retorno; este comportamiento es incorrecto y se ha corregido en JDK 7.
Ejemplo:

class A { int m(List<String> ls) { return 0; } long m(List<Integer> ls) { return 1; } }

Este código se compila bajo JDK 5.0 y JDK 6, y se rechaza bajo JDK 7.


Ejecuté el código de reflexión en Java 6.

Aquí está el código:

public static void main(String[] args) { Class<IMultiMap> immClass = IMultiMap.class; Method[] methods = immClass.getMethods(); for (Method method : methods) { if (method.getName().equals("put")) System.out.println(method.toString()); } }

Aquí están las firmas del método para la clase:

public abstract boolean IMultiMap.put(java.lang.Object,java.lang.Object) public abstract java.lang.Object java.util.Map.put(java.lang.Object,java.lang.Object)

O más concisamente:

boolean put(Object, Object) Object put(Object, Object)

Por lo tanto, se borran a los mismos parámetros con un tipo de retorno diferente. Supongo que es un error un caso de borde no especificado en Java 6 JLS, según la respuesta de Assylias. Me pregunto cómo Java 6 logró resolver estos métodos correctamente en tiempo de ejecución.

Edición: de acuerdo con el comentario de x4u, el código de bytes de la llamada mantiene una referencia a la firma completa cuando se compila, por lo que la JVM llama al método correcto. Dado que el compilador probablemente fue capaz de decir qué método estaba llamando debido a su acceso a la fuente (y por lo tanto a la información genérica), el compilador probablemente lo vinculó al método correcto a través de toda la firma. Interesante saber!