2013-10-14 11 views
5

Ho due costruttori che compilano bene, ma mi aspetterei che Java si lamentasse della possibilità di ambiguità.Costruttore argomento variabile _may_ conflitto, ma compila

public Foo(int id, Bar bar, String name, String description){ 
} 

public Foo(int id, Bar bar, String... values){ 
} 

Cosa dà?

+0

+1 Buona domanda. All'inizio ho interpretato male la tua domanda. –

risposta

7

Java consente a questi metodi di esistere, perché dispone di regole su quale sarà chiamato se entrambi si applicano. Nello specifico, il metodo fisso arity (senza ...) verrà scelto rispetto al metodo di aritmetica variabile (con ...).

Il JLS, Section 15.12.2, indica quanto segue per determinare quale metodo è scelto:

La prima fase (§15.12.2.2) esegue la risoluzione di sovraccarico senza consentire boxe o conversione unboxing, o l'uso di arietà variabile invocazione del metodo. Se non viene trovato alcun metodo applicabile durante questa fase , l'elaborazione continua fino alla seconda fase.

Questo garantisce che tutte le chiamate valide nella programmazione del Java lingua prima di Java SE 5.0 non sono considerati ambigui come il risultato della l'introduzione di metodi variabili arità, boxe implicita e/o unboxing. Tuttavia, la dichiarazione di un metodo di variabile aritmetica (§8.4.1) può modificare il metodo scelto per una determinata espressione del metodo di metodo , poiché un metodo di aritma variabile viene considerato come un metodo fisso nella prima fase. Ad esempio, dichiarando m (Object ...) in una classe che dichiara già m (Object) causa m (Object) a più lungo per alcune espressioni di chiamata (come m (null)), come m (Object []) è più specifico.

La seconda fase (§15.12.2.3) esegue la risoluzione di sovraccarico mentre consente il boxing e l'unboxing, ma preclude ancora l'utilizzo del richiamo del metodo arity variabile . Se non viene trovato alcun metodo applicabile durante questa fase , l'elaborazione continua fino alla terza fase.

Questo assicura che un metodo viene mai scelto attraverso variabile arity metodo invocazione se è applicabile attraverso arity fisso metodo chiamata.

La terza fase (§15.12.2.4) consente sovraccarico per essere combinato con metodi variabile Arity, boxe, e unboxing.

(sottolineatura mia)

codice Esempio:

class Bar{} 

public class Foo{ 
    public static void main (String [] args){ 
     Foo main = new Foo(1, new Bar(), "name", "description"); 
     Foo main2 = new Foo(2, new Bar(), "name"); 
     Foo main3 = new Foo(3, new Bar(), "name", "description", "otherValues"); 
     Foo main4 = new Foo(4, new Bar());  
    } 

    public Foo(int id, Bar bar, String name, String description) { 
     System.out.println("name and description!"); 
    } 

    public Foo(int id, Bar bar, String... values) { 
     System.out.println("values!"); 
    } 
} 

Questo stampa:

name and description! 
values! 
values! 
values! 

... per dimostrare che Java sceglierà il metodo arity fisso se può.

+1

Spiegazione molto chiara, grazie. – ajb

0

sono d'accordo con te Sean, il seguente codice potrebbe essere Calling uno dei due costruttori definite:

Foo foo = new Foo(3, new Bar(), "", ""); 

Tuttavia, quando il popolo java introdotto la "notazione di argomenti variabili", hanno deciso che quanto sopra definirebbe "il costruttore più specifico" definito. In questo caso ho 2 argomenti String e il tuo primo costruttore ha bisogno esattamente di 2 argomenti String, quindi verrà chiamato.

Il secondo costruttore sarà chiamata solo se ci sono più o meno di 2 argomenti stringa, ad esempio:

Foo foo = new Foo(3, new Bar(), "", "", ""); 

O anche:

Foo foo = new Foo(3, new Bar()); 

Mi auguro che aiuta a chiarire il motivo per cui don ottenere il compilatore di lamentarsi (è solo il modo in cui hanno deciso che dovrebbe funzionare).

Problemi correlati