Ich habe ein Problem in Java Generics, in denen der gleiche Code wird kompilieren und gut in Java 6, wird aber nicht kompilieren wegen der gleichen Löschung in Java 5. ich habe eine Datei TestErasure.java, die eine überladene Methode, die so genannte „Methode“:Unterschiedliches Verhalten zwischen Java 5 & 6 beim Überladen generischer Methoden
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>());
}
}
In Java 5, erhalte ich den erwarteten Übersetzungsfehler, die besagen, dass die Löschung der „Methode“ ist das gleiche:
$ 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
Java 6 kann jedoch denselben Code kompilieren und ausführen.
$ javac -version
javac 1.6.0_16
$ javac TestErasure.java
$ java TestErasure
method(List<Object> list)
method(List<String> list)
Basierend auf meinem gegenwärtiges Verständnis von Löschungen (dank Jon Skeet und Angelika Langer), erwartete ich eigentlich die Kompilierung-Fehler, wie geändert durch Java 5 (es sei denn, etwas geworfen, wie Java Generics behandelt - was ich nicht finden kann die Java 6 Release Notes). In der Tat, wenn ich den Rückgabetyp einer der überladenen Methoden ändern:
public static Object method(List<Object> list) ...
public static Object method(List<String> list) ...
Java 6 nicht auch wegen der gleichen Löschungen kompilieren:
$ 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
Es scheint, als ob der Rückgabetyp in Java 6 beeinflusst irgendwie die Auswahl welcher überladenen Methode zu verwenden?
Kann jemand herausfinden, warum das erste Beispiel in Java 6 funktioniert - es scheint gegen den angegebenen Umgang mit überlasteten generischen Methoden zu gehen?
Weitere Informationen:
Per David Vorschlag, das ursprüngliche Beispiel erfüllt durch Javac 1.6 wird 1.5 unter dem Java:
$ javac -target 1.5 TestErasure.java
$ java -version
java version "1.5.0_19"
$ java TestErasure
method(List<Object> list)
method(List<String> list)
der (gelöscht) Rückgabetyp Teil des m ist ethod Signatur in allen Versionen von Java. –
Der Rückgabetyp ist Teil des Methodendeskriptors, aber nicht die Methodensignatur, richtig? http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20a%20method%20signature? –
@Tom - Ich glaube, Sie irren sich - "Definition: Zwei der Komponenten einer Methodendeklaration umfassen die Methodensignatur - den Namen der Methode und die Parametertypen." Von http://java.sun.com/docs/books/tutorial/java/javaOO/methods.html. Die Methodensignatur muss für das Überladen von Methoden eindeutig sein und darf nicht den Rückgabetyp verwenden (zumindest für Java). – weiji