2009-09-16 11 views
18

Me he encontrado con un problema en Generics de Java en el que el mismo código se compilará y funcionará bien en Java 6, pero no se compilará debido a la misma eliminación en Java 5. tengo un TestErasure.java archivo que tiene un método sobrecargado, llamado "método":Comportamiento diferente entre Java 5 y 6 al sobrecargar métodos genéricos

import java.util.ArrayList; 
import java.util.List; 

public class TestErasure { 
public static Object method(List<Object> list) { 
    System.out.println("method(List<Object> list)"); 
    return null; 
} 

public static String method(List<String> list) { 
    System.out.println("method(List<String> list)"); 
    return null; 
} 

public static void main(String[] args) { 
    method(new ArrayList<Object>()); 
    method(new ArrayList<String>()); 
} 
} 

En Java 5, me sale el error de compilación, informando además que la supresión de "método" es la misma:

$ javac -version 
javac 1.5.0_19 
$ javac TestErasure.java 
TestErasure.java:10: name clash: method(java.util.List<java.lang.String>) and method(java.util.List<java.lang.Object>) have the same erasure 
     public static String method(List<String> list) { 
          ^
TestErasure.java:17: method(java.util.List<java.lang.Object>) in TestErasure cannot be applied to (java.util.ArrayList<java.lang.String>) 
     method(new ArrayList<String>()); 
      ^
2 errors 

Sin embargo, Java 6 puede compilar y ejecutar este mismo código.

$ javac -version 
javac 1.6.0_16 
$ javac TestErasure.java 
$ java TestErasure 
method(List<Object> list) 
method(List<String> list) 

En base a mi entendimiento actual de borrones (gracias a Jon Skeet y Angelika Langer), que en realidad espera que el error de compilación como lanzada por Java 5 (a menos que algo ha cambiado en la forma de Java maneja Genéricos - que no puedo encontrar en las notas de la versión de Java 6). De hecho, si modifico el tipo de retorno de uno de los métodos sobrecargados:

public static Object method(List<Object> list) ... 
public static Object method(List<String> list) ... 

Java 6 también falla al compilar debido a los mismos borrones:

$ javac TestErasure.java TestErasure.java:5: name clash: method(java.util.List<java.lang.Object>) and method(java.util.List<java.lang.String>) have the same erasure 
    public static Object method(List<Object> list) { 
         ^
TestErasure.java:10: name clash: method(java.util.List<java.lang.String>) and method(java.util.List<java.lang.Object>) have the same erasure 
    public static Object method(List<String> list) { 
         ^
2 errors 

Parece como si el tipo de retorno en Java 6 de alguna manera influye en la selección de qué método sobrecargado usar?

¿Alguien puede arrojar luz sobre por qué funciona el primer ejemplo en Java 6? Parece ir en contra del manejo establecido de los métodos genéricos sobrecargados?

Más información:

sugerencia de por David, el ejemplo original, compilado por javac 1.6, se ejecutará bajo la Java 1.5:

$ javac -target 1.5 TestErasure.java 
$ java -version 
java version "1.5.0_19" 
$ java TestErasure 
method(List<Object> list) 
method(List<String> list) 
+0

el (borrado) tipo de retorno es parte de la m firma de ethod en todas las versiones de Java. –

+0

El tipo de devolución es parte del descriptor del método, pero no la firma del método, ¿correcto? http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20a%20method%20signature? –

+1

@Tom - Creo que está equivocado - "Definición: Dos de los componentes de una declaración de método comprenden la firma del método, el nombre del método y los tipos de parámetros". De http://java.sun.com/docs/books/tutorial/java/javaOO/methods.html. La firma del método debe ser única para que la sobrecarga de métodos funcione, y no dependen del tipo de devolución (para Java, al menos). – weiji

Respuesta

Cuestiones relacionadas