2014-12-15 18 views
18

Warum in diesem Code kein Compiler-Fehler ist: gibtJava Überlastung mit variabler Länge Argumente

public class OverloadingVarArgs 
{ 
    public void fun1(int... b) 
    { 
     System.out.println("int"); 
    } 
    public void fun1(long... a) 
    { 
     System.out.println("long"); 
    } 
    public static void main(String[] args) 
    { 
     OverloadingVarArgs obj = new OverloadingVarArgs(); 
     obj.fun1(); 
    } 

} 

Aber dieser Code Fehler kompilieren!

Ich glaube, es sollte in beiden Fällen kompilieren Fehler sein, aber das ist nicht so.

+0

Bitte den Kompilierfehler vollständig posten. –

+1

Der Fehler für die zweite, die er bekommt, ist: 'Fehler: Verweis auf fun1 ist mehrdeutig, beide Methoden fun1 (int ...) in Main und Methode fun1 (boolean ...) im Hauptmatch obj.fun1(); ^ 1 Fehler ' – Sid

+0

@Sid Dann müssten beide Codebeispiele zu einem Compilerfehler führen, da beide Methoden nicht eindeutig sind. – mezzodrinker

Antwort

4

Wenn Sie int und long (vergleichbare Typen), wird der kleinste standardmäßig verwendet werden, die int ist (da Sie kein Argument übergeben) - Ich denke, es ist, weil intkann-long erweitern, sondern long kann nicht (außer Sie explizit es umwandeln), wählt der Compiler den niedrigsten Genauigkeitstyp.

Aber wenn man boolean und int haben, kann der Vergleich nicht durchgeführt werden, und Sie werden zur Auswahl des richtigen ladenen Methode

The method fun1(int[]) is ambiguous for the type OverloadingVarArgs 
+0

Sie sagen also, weil die Typen vergleichbar sind, kann der Compiler auflösen, welche Methode aufgerufen wird, indem Sie den Typ mit der niedrigsten Genauigkeit auswählen. Im Gegensatz zur Inkompatibilität zwischen 'boolean' und' int'? – christopher

+0

@christopher Das ist, was ich denke .. – Maroun

+0

@christopher, du hast Recht. – Sid

9

Die Regeln zu erhalten sind wie folgt:

  • Primitive Erweiterung Anwendungen das kleinste mögliche Methodenargument
  • Wrapper-Typ kann nicht auf einen anderen Wrapper-Typ erweitert werden
  • Sie können von Int zu Integer Box und Erweitern zu Objekt, aber nicht zu Long
  • Verbreiterung Beats Boxen, Beats Var-Args.
  • Sie können Box und dann Widen
  • Sie können nicht Widen und dann Box (Objekt über Integer Ein int werden kann) (Ein int kann lange nicht geworden)
  • Sie können keine var-args, entweder mit Verbreiterung oder Boxen
  • kombinieren

Schauen Sie sich diese letzte Regel an. Sie können nicht kombinieren Erweiterung oder Boxen mit variabler Länge Argumente. Das bedeutet, dass die Typen in keiner Weise manipuliert werden können und Sie den Vergleich so durchführen müssen, wie er ist. int und long kann verglichen werden, kein Problem und der Compiler kann folgern, dass int der kleinere der beiden ist. Nach der ersten Regel wird es nach dem kleinsten möglichen Methodenargument gehen, daher hat es den richtigen (und einzigen) Weg zu einer Methode ausgearbeitet.

Wenn Sie jedoch zu boolean und int bekommen, gibt es keine Vergleichsverfahren zwischen den beiden wegen Java starke Typisierung. Ohne Wissen, welcher Typ am kleinsten ist, hat der Compiler absolut keine Ahnung, welche Methode du meinst.

visuellere Beispiel

ist es für Schritt aus der Sicht des Compilers Schritt nehmen lassen. Zuerst mit int und long.

int und lange

Schritt 1 - Überprüfen, ob die Parameter alle Argumente übereinstimmen und wenn ja, welche man es genau mit

Nun, bedeutet varargs, dass Sie 0 zu viele Argumente übergeben können . In diesem Fall haben Sie sich dafür entschieden, die Argumente 0 zu übergeben. Daher entspricht Ihr Anruf sowohl dem Typ int als auch dem Typ long.

Schritt 2 - Versuchen, Autobox oder erweitern. Dies sollte helfen, herauszufinden, welche für

Sie Varargs verwenden, so dass der Compiler weiß, dass es dies nicht tun kann, wie in der endgültigen Regel.

Schritt 3 - Versuch, herauszufinden, welche Art

Der Compiler ist in der Lage kleinste ist die Art int mit dem Typ long zu vergleichen. Daraus ergibt sich, dass der int der kleinste Typ ist.

Schritt 4 - Stellen Sie den Anruf

Mit dem Wissen, dass int die kleinste Art ist, es geht dann um den Wert der Methode zur Ausführung.

Okay, und jetzt machen wir das gleiche mit boolean und int.

boolean und int

Schritt 1 - Überprüfen, ob die Parameter alle Argumente übereinstimmen und wenn ja, welche sie paßt genau

Die gleiche Geschichte. Sie haben nichts erreicht, das mit beiden Argumenten übereinstimmt.

Schritt 2 - Versuchen, Autobox oder erweitern. Dies sollte helfen, herauszufinden, welche für

Wie oben, Sie dürfen dies nicht tun, weil Sie Varargs verwendet.

Schritt 3 - Versuch, herauszufinden, welche Art

Dies ist der entscheidende Unterschied am kleinsten ist. Hier sind die Typen nicht vergleichbar. Dies bedeutet, dass der Compiler nicht weiß, welche Methode Sie mit den Parametern oder vom kleinsten Typ aufrufen möchten. Ergo, es war nicht in der Lage, die richtige Route auszuarbeiten.

Schritt 4 - Machen Sie den Anruf

Ohne das Wissen davon, welche Methode zu nennen, es Ausführung nicht fortgesetzt werden kann und wirft die entsprechende Ausnahme.

5

In Ihrem zweiten Beispiel kann der Compiler nicht die spezifischste Methode ermitteln, die aufgerufen werden soll. Die wesentlichen Details werden in the language spec erklärt, aber im Wesentlichen, wenn zwei Variable-Arity-Methoden (var-arg) verglichen werden, dann wenn Methode A die an Methode B übergebenen Argumente akzeptieren könnte, aber nicht umgekehrt Methode B ist am spezifischsten.

In Ihrem ersten Beispiel werden die rules of primitive sub-typing angewendet, die da sind:

double >1 float

float >1 long

long >1 int

int >1 char

int >1 short

short >1 byte

(Where >1 means 'direct supertype of')

Hier können wir sehen, dass ein int als ein long spezifischere, so dass Ihre fun1(int... b) Methode gewählt wird. Im zweiten Beispiel wählt der Compiler zwischen int und boolean. Es gibt keine Untertyp-Beziehung zwischen diesen primiritve Typen, daher gibt es keine spezifischste Methode und "der Methodenaufruf ist mehrdeutig und ein Fehler bei der Kompilierung tritt auf." (letzte Zeile in 15.12.2.5).

Verwandte Themen