2010-07-15 20 views
7

Eventuali duplicati:
Is this valid Java?Funzionalità o errore: perché viene compilato questo codice Java?

sono rimasto sorpreso di scoprire la classe Java sotto compila. Ha diversi metodi, con lo stesso nome, numero di argomenti e seguenti tipi di argomenti di cancellazione del tipo. Tuttavia, compila e funziona come previsto, su Windows utilizzando varie versioni del compilatore Sun JDK 1.6. Quindi, se questo è un bug è stato intorno per le età ....

Essa ha anche compilato con numerose versioni di Eclipse, ma non il compilatore con il compilatore fornito con Eclipse 3.6

Oltre codice chiamante funziona come previsto - vale a dire. non ci sono errori sui metodi ambigui sul codice chiamante.

Se eseguire iterazioni su metodi restituiti da ErasureExample.class.getMethods() sono tutti presenti .....

Secondo il JLS sarebbe illegale se i metodi hanno "sovrascrivono-equivalente" firme - rigorosamente non lo fanno, in quanto nessuno di Collection, Collection o Collection sono override equivalenti .... se questo è il caso Eclipse è errato, JDK corretto ...

Feature or bug? Dovrebbe essere compilato?

/** 
* Demonstrates that a class with methods that differ only by return type can exist. 
* Section 8.4 of the JLS suggests this is an error IFF the methods had 
* override equivalent signatures, which they dont'' 
* 
* 
* From JLS 8.4... 

* It is a compile-time error for the body of a class to declare as members two methods 
* with override-equivalent signatures (§8.4.2) (name, number of parameters, and types 
* of any parameters). 
* 
* Should it compile? 
*/ 
public class ErasureExample { 
    // note the single Collection<Integer> argument... 
    public static int[] asArray(Collection<Integer> vals) { 
     if (vals == null) 
     return null; 

     int idx = 0; 
     int[] arr = new int[vals.size()]; 
     for (Integer i : vals) { 
     arr[idx] = i==null? 0 : i.intValue(); 
     idx++; 
     } 
     return arr; 
    } 

    // same method name as above, type differs only by generics.... surely this violates 8.4 of JLS... 
    public static long[] asArray(Collection<Long> vals) { 
     if (vals == null) 
     return null; 

     int idx = 0; 
     long[] arr = new long[vals.size()]; 
     for (Long i : vals) { 
     arr[idx] = i==null? 0 : i.longValue(); 
     idx++; 
     } 
     return arr; 
    } 

    // same method name as above, type differs only by generics.... surely this violates 8.4 of JLS... 
    public static boolean[] asArray(Collection<Boolean> vals) { 
     if (vals == null) 
     return null; 

     int idx = 0; 
     boolean[] arr = new boolean[vals.size()]; 
     for (Boolean b : vals) { 
     arr[idx] = b==null? false : b.booleanValue(); 
     idx++; 
     } 
     return arr; 
    } 

} 

risposta

-3

Questi metodi non hanno le stesse firme. Diversi valori di ritorno e diversi tipi di parametri. Sì, i generici fanno una grande differenza. Tutto sembra a posto qui.

+7

correzione: il valore restituito non fa parte della firma – schar

+5

In realtà, a livello bytetec, i descrittori del metodo contengono anche il tipo restituito e possono essere utilizzati per differenziarli. A volte il compilatore può trarre vantaggio da questo, controllando il tipo di variabile in cui si salva il risultato, dal momento che il compilatore può dire quale metodo dovrebbe essere chiamato, e nel bytecode è solo l'istruzione 'call method with descriptor this-and- quella'. Non è esattamente giusto, secondo le specifiche, ma il compilatore lo consente per ora. Apparentemente in Java 7 potrebbero cambiare questo. –

+1

Dopo aver giocato un po 'con questo codice, trovo la spiegazione di Andrei Fierbinteanu la più convincente. Sembra che non ci siano problemi pratici con i metodi di compilazione con firma identica, dal momento che le chiamate nel bytecode sono basate su ID numerici univoci dei metodi. Alcuni compilatori approfittano del fatto che hanno informazioni generiche per renderlo possibile. Questo causa problemi. Vedi ad esempio cosa succede con reflection: ErasureExample.class.getDeclaredMethod ("asArray", Collection.class) restituisce il primo metodo nel codice sorgente! (Es. Riordinare il codice cambia le cose) –

2

Il compilatore è abbastanza intelligente da disambiguare i metodi in fase di compilazione, sebbene alla fine esegua la cancellazione dei tipi. L'intero punto di parametrizzazione dei generici è di fornire un controllo di sicurezza del tipo in fase di compilazione, il tipo di cancellazione è solo un dettaglio di implementazione.

Problemi correlati