I stumbled upon this snippet:
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);
}
}
This will result in a compile error:
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
How is this ambiguous? Shouldn't only the second parameter be promoted in this case since the first parameter is already an int? The first param need not be promoted in this case right?
The compilation succeeds if I update the code to add another method:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
Let me expand just to clarify. The code below results in ambiguity:
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);
}
}
Then this code below also results in ambiguity:
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);
}
}
However this one does not result in ambiguity:
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);
}
}
I think this has something to do with JLS's specific rule about 15.12.2.5. Choosing the Most Specific Method. It states that:
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
How Java chooses the most specific method is further explained by the text:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error. In cases such as an explicitly typed lambda expression argument (§15.27.1) or a variable arity invocation (§15.12.2.4), some flexibility is allowed to adapt one signature to the other.
In the case of your example, all methods are accessible and applicable to method invocation, therefore, Java needs to determine which of them is most specific.
For these methods, none can be determined to be more specific:
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
} // int, double cannot be passed to long, long or double, long without error
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
} // long , long cannot be passed to int, double or double, long without error
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
} // double, long cannot be passed to int, double or long, long without error
The fourth method clears ambiguity precisely because it fulfills the necessary condition to be most specific.
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
That is, (int, long) can be passed to (int, double), (long, long), or (double, long) without compilation errors.