Der folgende Code erzeugt den Syntaxfehler:
Die Methode
f(int[])
ist für den Typ C mehrdeutig
Mein Code:
public class C{
public static void f(int... i)
{
System.out.println("a");
}
public static void f(Integer... i)
{
System.out.println("b");
}
public static void main(String[] args) {
f(new Integer(2));
}
}
Wenn ich Array-Notation verwende []
anstatt der ...
und rufen Sie die Funktion korrekt mit auf f(new Integer[]{3,4,5})
kann der Compiler richtig entscheiden, welche Methode ich verwenden möchte.
Aus welchem Grund kann der Compiler nicht entscheiden, mit welcher Funktion er aufgerufen wird ...
?
Antworten:
2 für die Antwort № 1Die Suche nach der "richtigen" Methode für eine bestimmte Aufrufstelle wird in beschrieben JLS, Abschnitt 15.12, "Methodenaufrufausdrücke". Nach einem kurzen Vorspiel mit grundlegenden Sanitätsprüfungen beginnt der relevante Teil bei Abschnitt 15.12.2.1, Identifizieren potenziell anwendbarer Methoden. In Ihrem Fall sind beide Methoden möglicherweise anwendbarnach dieser Definition.
Der nachfolgende Prozess besteht aus drei Phasen. In Ihrem Fall ist die Methode a variable arity Methode (aufgrund der "varargs"). So fängt es gleich bei an 15.12.2.4, Phase 3: Identifizieren Sie die anwendbaren Methoden der variablen Arität.
Die Methode m ist genau dann eine anwendbare Variable-Arity-Methode, wenn alle der folgenden Bedingungen erfüllt sind:
- Für 1 ≤ i <n kann der Typ von ei, Ai, durch Methodenaufruf-Umwandlung in Si umgewandelt werden.
- ...
(die anderen Bedingungen sind hier nicht relevant)
Das Methodenaufrufkonvertierung (JLS, 5.3) erlaubt folgende Konvertierungen:
- eine Identitätsumwandlung (§5.1.1)
- eine sich erweiternde primitive Konvertierung (§5.1.2)
- eine erweiterte Referenzumrechnung (§5.1.5)
- eine Boxkonvertierung (§5.1.7), optional gefolgt von einer erweiterten Referenzkonvertierung
- eine Unboxing-Konvertierung (§ 5.1.8), optional gefolgt von einer sich erweiternden primitiven Konvertierung
Die Umwandlung von Integer
zu Integer
ist eine Identitätsumwandlung (erster Aufzählungspunkt). Die Umwandlung von Integer
zu int
ist eine Unboxing-Konvertierung (letzter Aufzählungspunkt).
Beide Methoden sind also "anwendbare Variable-Arity-Methoden" gemäß der Spezifikation.
0 für die Antwort № 2
Varargs
und Boxing
wurden beide ab Java 5 eingeführt.Bei Java 5 kam es zu Problemen mit dem Umgang mit veraltetem Code, bei dem der Compiler eine Verbreitungsoperation ausgeführt hat (z. B. wenn es lang ist, wählt der Compiler lang Integer, da die Erweiterung von int auf long vor Java 5 zulässig war), aber da varargs und Boxing befindet sich auf derselben Ebene (Java 5 und höher). Der Compiler kann den korrekten Typ nicht ermitteln
Es gibt keine definierte Präferenz zwischen Varargs und Boxen / Unboxing, wenn sie in Kombination verwendet werden
0 für die Antwort № 3
Die Regel ist WBV/WAV
Verbreiterung -> (Auto) Boxen -> Varargs im Falle von Überladen der Methode.
Erweiterung
int -> long -> float -> double
Boxen
Integer -> Number -> Object
a) Verbreiterung dann Varargs
int... -> long... -> float... -> double...
b) Boxen dann Varargs
Integer... -> Number... -> Object...
In anderen Worten
Varargs [Last option]
^
|
Boxing [Newer style, added in Java 1.5]
^
|
Widening [Older style, choosen by the compiler to support existing code]
Hinweis:
Boxing
dannWidening
ist auch erlaubt.Varargs
dannBoxing
ist nicht erlaubt.Varargs
wird als letzte Option zwischen behandeltWidening
undboxing
- Wählt entweder
Widening then Varargs
oderBoxing then Varargs
. Wenn beide Möglichkeiten vorhanden sind, ergibt sich daraus mehrdeutig Methodenaufruf.
Die Konvertierung in Ihrem Fall von f(new Integer(2))
. Wie in der Regel Boxing
dann Widening
Integer -> Number -> Object -> int -> long -> float -> double
Nun gibt es 2 Möglichkeiten neben double
3.a) Verbreiterung dann Varargs (
int...
)3.b) Boxen dann Varargs (
Integer...
)
aber beide sind anwesend und führen zu mehrdeutig Methodenaufruf.
Die Konvertierung in Ihrem Fall von f(new Integer[]{3,4,5})
Integer...
ist direkte Übereinstimmung. Varargs
dann Boxing
ist nicht erlaubt.
-2 für die Antwort № 4
Das ... ist für eine variable Anzahl von Argumenten gedacht. Sie müssen die Werte wie f (1, 2, 3) übergeben.