2009-09-16 13 views
18

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) 
+0

der (gelöscht) Rückgabetyp Teil des m ist ethod Signatur in allen Versionen von Java. –

+0

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? –

+1

@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

Antwort

Verwandte Themen