Ich bin auf diesen Ausschnitt gestoßen:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
}
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
Dies führt zu einem Kompilierungsfehler:
Fehler: (15, 9) Java: Der Verweis auf printSum ist mehrdeutig, sowohl die Methode printSum (int, double) in ParamTest als auch die Methode printSum (long, long) in ParamTest stimmen überein
Wie ist das mehrdeutig? Sollte in diesem Fall nicht nur der zweite Parameter heraufgestuft werden, da der erste Parameter bereits ein int ist? Der erste Parameter muss in diesem Fall nicht befördert werden, oder?
Die Kompilierung ist erfolgreich, wenn ich den Code aktualisiere, um eine weitere Methode hinzuzufügen:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
Lassen Sie mich nur zur Klarstellung erweitern. Der folgende Code führt zu Mehrdeutigkeiten:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
Dann führt dieser Code unten auch zu Mehrdeutigkeiten:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
Dies führt jedoch nicht zu Mehrdeutigkeiten:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, double b) {
System.out.println("In longDBL " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
quelle
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
- Es ist nicht die Methode, die mehrdeutig ist, sondern der Aufruf der Methode, die nicht eindeutig ist.Antworten:
Ich denke, das hat etwas mit der spezifischen Regel von JLS vom 15.12.2.5 zu tun . Auswahl der spezifischsten Methode . Es sagt, dass:
Wie Java die spezifischste Methode auswählt , wird im Text näher erläutert:
In Ihrem Beispiel sind alle Methoden zugänglich und auf den Methodenaufruf anwendbar. Daher muss Java bestimmen, welche davon am spezifischsten ist .
Für diese Methoden kann keine spezifischer bestimmt werden:
Die vierte Methode löscht Mehrdeutigkeiten genau deshalb, weil sie die notwendige Bedingung erfüllt, um am spezifischsten zu sein .
Das heißt, (int, long) kann ohne Kompilierungsfehler an (int, double), (long, long) oder (double, long) übergeben werden.
quelle
Das ist in der Tat eine sehr interessante Frage. Lassen Sie uns Schritt für Schritt die Java-Sprachspezifikation durchgehen.
Wenn der Compiler versucht, potenziell anwendbare Methoden zu identifizieren, sucht er zunächst nach Methoden, die durch Strict Invocation anwendbar sind .
In Ihrem Fall gibt es keine solchen Methoden. Der nächste Schritt besteht darin , Methoden zu finden, die für Loose Invocation anwendbar sind
Zu diesem Zeitpunkt stimmen alle Methoden überein, sodass die spezifischste Methode ( §15.12.2.5 ) unter den Methoden ausgewählt wird, die durch losen Aufruf anwendbar sind.
Dies ist ein Schlüsselmoment, also schauen wir uns das genauer an.
(Wir interessieren uns nur für den folgenden Fall):
Einfach ausgedrückt ist eine Methode spezifischer, wenn alle Parametertypen spezifischer sind . Und
Ausdruck
S <: T
bedeutet, dass diesS
ein Subtyp von istT
. Für Primitive haben wir folgende Beziehung:Schauen wir uns also Ihre Methoden an und sehen, welche spezifischer ist als andere.
In diesem Beispiel ist der erste Parameter der Methode 1 offensichtlich spezifischer als der erste Parameter der Methode 2 (wenn Sie sie mit ganzzahligen Werten aufrufen :)
printSum(1, 2)
. Der zweite Parameter ist jedoch spezifischer für die Methode 2 , weillong < double
. Keine dieser Methoden ist spezifischer als die andere. Deshalb haben Sie hier eine Mehrdeutigkeit.Im folgenden Beispiel:
Der erste Parametertyp der Methode 1 ist spezifischer als der in Methode 2, da
int < long
der zweite Parametertyp für beide gleich ist. Deshalb wird die Methode 1 ausgewählt.quelle
double
ist nicht spezifischer alslong
. Und damit die Methode gewählt werden kann, müssen alle Typparameter spezifischer sein: Typ Si ist spezifischer als Ti für das Argument ei für alle i (1 ≤ i ≤ n, n = k)weil der int-Wert in Java auch als double betrachtet werden kann. Mittel
double a = 3
ist gültig und gleich mit dem langen.long b = 3
Deshalb schafft es eine Mehrdeutigkeit. Du rufst anIst für alle drei Methoden verwirrend, da alle drei gültig sind:
Sie können das L am Ende setzen, um anzugeben, dass es ein langer Wert ist. zum Beispiel:
für double musst du es konvertieren:
Lesen Sie auch den Kommentar von @Erwin Bolwidt
quelle