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)
el (borrado) tipo de retorno es parte de la m firma de ethod en todas las versiones de Java. –
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? –
@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