Natknąłem się na ten fragment:
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);
}
}
Spowoduje to błąd kompilacji:
Błąd: (15, 9) java: odwołanie do printSum jest niejednoznaczne, zarówno metoda printSum (int, double) w ParamTest, jak i metoda printSum (długa, długa) w ParamTest
Jak to jest niejednoznaczne? Czy w tym przypadku nie należy promować tylko drugiego parametru, ponieważ pierwszy parametr jest już liczbą całkowitą? Pierwszy param nie musi być promowany w tym przypadku, prawda?
Kompilacja powiedzie się, jeśli zaktualizuję kod, aby dodać inną metodę:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
Pozwól, że rozwinę się, aby wyjaśnić. Poniższy kod powoduje niejednoznaczność:
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);
}
}
Zatem poniższy kod również powoduje niejednoznaczność:
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);
}
}
Jednak nie powoduje to dwuznaczności:
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);
}
}
java
java-8
type-promotion
riruzen
źródło
źródło
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
- to nie jest metoda dwuznaczna, to wywołanie metody niejednoznacznej.Odpowiedzi:
Myślę, że ma to związek z konkretną regułą JLS dotyczącą 15.12.2.5. Wybór najbardziej szczegółowej metody . Twierdzi, że:
Sposób, w jaki Java wybiera najbardziej szczegółową metodę, wyjaśniono w dalszej części tekstu:
W naszym przykładzie wszystkie metody są dostępne i mają zastosowanie do wywoływania metod, dlatego Java musi określić, która z nich jest najbardziej specyficzna .
W przypadku tych metod nie można określić bardziej szczegółowej:
Czwarta metoda usuwa niejasności właśnie dlatego, że spełnia warunek konieczny, aby być najbardziej szczegółowym .
Oznacza to, że (int, long) można przekazać do (int, double), (long, long) lub (double, long) bez błędów kompilacji.
źródło
To jest naprawdę bardzo interesujące pytanie. Przejdźmy krok po kroku do specyfikacji języka Java.
Kiedy kompilator próbuje zidentyfikować potencjalnie odpowiednie metody, pierwszą rzeczą, jaką robi, jest wyszukiwanie metod stosowanych przez Strict Invocation .
W twoim przypadku nie ma takich metod, więc następnym krokiem jest znalezienie metod mających zastosowanie w przypadku luźnego wywołania
W tym momencie wszystkie metody się zgadzają, więc najbardziej szczegółowa metoda ( §15.12.2.5 ) jest wybierana spośród metod, które można zastosować w drodze luźnego wywołania.
To kluczowy moment, więc przyjrzyjmy się temu z bliska.
(Interesuje nas tylko następujący przypadek):
Mówiąc najprościej, metoda jest bardziej szczegółowa, jeśli wszystkie jej typy parametrów są bardziej szczegółowe . I
Wyrażenie
S <: T
oznacza, żeS
jest to podtypT
. W przypadku prymitywów mamy następujący związek:Spójrzmy więc na twoje metody i zobacz, która z nich jest bardziej szczegółowa niż inne.
W tym przykładzie pierwszy parametr metody 1 jest oczywiście bardziej szczegółowy niż pierwszy parametr metody 2 (jeśli wywołasz je z wartościami całkowitymi:)
printSum(1, 2)
. Ale drugi parametr jest bardziej szczegółowy dla metody 2 , ponieważlong < double
. Żadna z tych metod nie jest bardziej szczegółowa niż inna. Dlatego masz tu dwuznaczność.W poniższym przykładzie:
pierwszy typ parametru w metodzie 1 jest bardziej szczegółowy niż ten w metodzie 2, ponieważ
int < long
i drugi typ parametru jest taki sam dla obu z nich, dlatego wybrano metodę 1.źródło
double
nie jest bardziej szczegółowy niżlong
. Aby wybrać metodę, wszystkie parametry typu muszą być bardziej szczegółowe: typ Si jest bardziej szczegółowy niż Ti dla argumentu ei dla wszystkich i (1 ≤ i ≤ n, n = k)ponieważ wartość int może być również uważana za podwójną w java. środki
double a = 3
są ważne i to samo z długimlong b = 3
Więc dlatego tworzy niejednoznaczność. Ty dzwoniszJest mylący dla wszystkich trzech metod, ponieważ wszystkie te trzy są poprawne:
Możesz umieścić L na końcu, aby określić, że jest to długa wartość. na przykład:
podwójnie musisz go przekonwertować:
przeczytaj także komentarz @Erwin Bolwidt
źródło