2012-01-12 3 views
13

Mi chiedevo perché non è consentito in Java sovraccaricare Foo(Object[] args) con Foo(Object... args), sebbene siano utilizzati in un modo diverso?Perché in Java non è consentito sovraccaricare Foo (Object ...) con Foo (Object [])?

Foo(Object[] args){} 

viene utilizzato come:

Foo(new Object[]{new Object(), new Object()}); 

mentre l'altra forma:

Foo(Object... args){} 

viene utilizzato come:

Foo(new Object(), new Object()); 

C'è un motivo dietro questo?

+0

domanda interessante +1 – mKorbel

+1

Forse mi manca qualcosa, ma perché è necessario un sovraccarico? Se dichiari il tuo metodo come "void foo (Object ... args)" allora puoi chiamarlo con ** o ** 'foo (nuovo Object(), new Object())' ** o ** 'foo (nuovo Object [] {new Object(), new Object()}) 'e ottiene lo stesso risultato. Vedi [questa domanda correlata] (http://stackoverflow.com/questions/1656901/varargs-and-the-argument) per un esempio. –

+0

il vararg è solo un flag alla firma del metodo che trasmuta l'ultimo array dichiarato (come 'int []' o 'Object []') al tipo vararg. A parte questo, nessuna differenza tra le firme del metodo. La stessa domanda sarebbe come non poter sovraccaricare il metodo 'private' e' public'. – bestsss

risposta

25

Questo 15.12.2.5 Choosing the Most Specific Method parla di questo, ma è piuttosto complesso. per esempio. Scegliere tra Foo (Numero ... ints) e Foo (Intero ... ints)

Nell'interesse della retrocompatibilità, questi sono effettivamente la stessa cosa.

public Foo(Object... args){} // syntactic sugar for Foo(Object[] args){} 

// calls the varargs method. 
Foo(new Object[]{new Object(), new Object()}); 

, ad es. è possibile definire main() come

public static void main(String... args) { 

Un modo per renderli diversi è quello di prendere un argomento prima che i varargs

public Foo(Object o, Object... os){} 

public Foo(Object[] os) {} 

Foo(new Object(), new Object()); // calls the first. 

Foo(new Object[]{new Object(), new Object()}); // calls the second. 

Essi non sono esattamente gli stessi. La sottile differenza è che mentre si può passare un array a un vararg, non si può trattare un parametro dell'array come vararg.

public Foo(Object... os){} 

public Bar(Object[] os) {} 

Foo(new Object[]{new Object(), new Object()}); // compiles fine. 

Bar(new Object(), new Object()); // Fails to compile. 

Inoltre, un varag deve essere l'ultimo parametro.

public Foo(Object... os, int i){} // fails to compile. 

public Bar(Object[] os, int i) {} // compiles ok. 
+0

+1 bella spiegazione. Esistono specifiche linguistiche scritte per questo? –

+0

:-) bella risposta +1 – mKorbel

+0

Dai un'occhiata a [questa domanda] (http://stackoverflow.com/q/14937948/597657) per favore. –

3

La risposta più diretta alla domanda è che avendo entrambe le dichiarazioni creerebbe un'ambiguità nella logica metodo di ricerca. Se hai dichiarato sia nella stessa classe, non ci sarebbe alcun modo per capire quale metodo si voleva quando si chiama così:

Object[] a = new Object[10]; 
Foo(a); // array or vararg? 

e Java richiede che ci sia sempre un metodo più specifico per ogni chiamata di metodo. Per il perché, vedere la risposta di Pietro.

+0

sono * esattamente * gli stessi, non ambiguità, semplicemente non possono esistere nella stessa classe – bestsss