2013-10-14 6 views
5

Ich habe zwei Konstruktoren, die gut kompilieren, aber ich würde erwarten, Java über die Möglichkeit der Mehrdeutigkeit zu beschweren.Variabler Argumentkonstruktor _may_ Konflikt, aber kompiliert

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

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

Was gibt?

+0

+1 Gute Frage. Ich habe Ihre Frage zunächst falsch interpretiert. –

Antwort

7

Java erlaubt diese Methoden zu existieren, weil es Regeln darüber gibt, welche davon aufgerufen wird, wenn beide gelten. Insbesondere wird die Methode mit fester Arity (ohne ...) über die Variable Arity-Methode (mit ...) ausgewählt.

Die JLS, Section 15.12.2, lautet wie folgt, wenn bestimmt wird, welche Methode gewählt wird:

die erste Phase (§15.12.2.2) Überlast Auflösung ohne ermöglicht Boxen oder unboxing Umwandlung oder die Verwendung von variablen arity führt Methodenaufruf. Wird in dieser Phase keine zutreffende Methode gefunden, geht die Verarbeitung in die zweite Phase über.

Dies gewährleistet, dass alle Anrufe, die in der Java-Programmierung Sprache vor Java SE 5.0 gültig waren, sind nicht mehrdeutig betrachtet als das Ergebnis der Einführung variabler arity Methoden, impliziter Boxen und/oder Unboxing. Die Deklaration einer Variablenaritätsmethode (§8.4.1) kann jedoch die für einen bestimmten Methodenmethodenaufruf gewählte Methode ändern, da in der ersten Phase eine variable Arity-Methode als feste Methode behandelt wird. Wenn beispielsweise m (Object ...) in einer Klasse deklariert wird, die bereits m (Object) deklariert, wird m (Object) auf länger für einige Aufrufausdrücke (wie m (null)) als m (Objekt []) ist spezifischer.

Die zweite Phase (§15.12.2.3) führt eine Überladungsauflösung durch, während Boxing und Unboxing erlaubt, aber die Verwendung der Variable Arity-Methodenaufruf immer noch ausschließt. Wenn während dieser Phase keine zutreffende Methode gefunden wird, wird die Verarbeitung in der dritten Phase fortgesetzt.

Dies stellt sicher, dass ein Verfahren niemals durch variable arity Methodenaufruf wird gewählt, wenn es fest anwendbar durch arity Methode Aufruf ist.

Die dritte Phase (§15.12.2.4) ermöglicht das Kombinieren von Überladung mit variablen Variablenmethoden , Boxen und Unboxing.

(Hervorhebung von mir)

Beispielcode:

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!"); 
    } 
} 

Dies gibt:

name and description! 
values! 
values! 
values! 

... um zu zeigen, dass Java die feste arity Methode, wenn es abholt kann.

+1

Sehr klare Erklärung, danke. – ajb

0

Ich stimme Ihnen Sean, der folgende Code könnte jeder der beiden Konstrukteure anrufen Sie definiert:

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

Wenn jedoch die Java-Menschen die „variable Argument Notation“ eingeführt, entschieden sie sich, dass die oben würde "den spezifischsten Konstruktor" definieren. In diesem Fall habe ich 2 String-Argumente, und Ihr erster Konstruktor benötigt genau 2 String-Argumente, so dass er aufgerufen wird.

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

Oder auch:

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

hoffe ich, dass, warum Sie don zu klären hilft

wird Der zweite Konstruktor nur mehr oder weniger als 2 String Argumente, zum Beispiel, wenn es aufgerufen werden Der Compiler sollte sich nicht beschweren (es ist nur so, wie sie entschieden haben, dass es funktionieren sollte).

Verwandte Themen