2009-09-16 2 views
18

Ho incontrato un problema in Java Generics in cui lo stesso codice si compilerà e funzionerà correttamente in Java 6, ma non riuscirà a compilare a causa della stessa cancellazione in Java 5. ho un TestErasure.java di file che ha un metodo di overload, chiamato "metodo":Differente comportamento tra Java 5 e 6 quando si sovraccaricano metodi generici

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, ottengo l'errore di compilazione atteso, affermando che la cancellazione di "metodo" è lo stesso:

$ 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 

Tuttavia, Java 6 è in grado di compilare ed eseguire questo stesso codice.

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

In base alla mia attuale comprensione di cancellature (grazie a Jon Skeet e Angelika Langer), in realtà ho atteso l'errore di compilazione come gettata da Java 5 (a meno che qualcosa è cambiato nel modo in cui ha gestito Java generici - che non riesco a trovare su le note di rilascio di Java 6). Infatti, se modifico il tipo di ritorno di uno dei metodi di overload:

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

Java 6 non riesce inoltre a compilare causa delle stesse cancellature:

$ 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 

Sembra come se il tipo di ritorno in Java 6 influenza in qualche modo la selezione di quale metodo di overload usare?

Qualcuno può far luce sul motivo per cui il primo esempio funziona in Java 6 - sembra andare contro la gestione dichiarata di metodi generici sovraccaricati?

Maggiori informazioni:

suggerimento di Per David, l'esempio originale, rispettato da javac 1.6, verrà eseguito sotto 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

l'(cancellato) tipo di ritorno fa parte del m firma ethod in tutte le versioni di Java. –

+0

Il tipo restituito fa parte del descrittore del metodo, ma non della firma del metodo, corretto? http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20a%20method%20signature? –

+1

@ Tom - Credo che tu stia sbagliando - "Definizione: due dei componenti di una dichiarazione di metodo comprendono la firma del metodo, il nome del metodo e i tipi di parametro." Da http://java.sun.com/docs/books/tutorial/java/javaOO/methods.html. La firma del metodo deve essere univoca perché l'overloading del metodo funzioni e non si basano sul tipo restituito (almeno per Java). – weiji

risposta