Reputation: 3555
I am learning Java, and met some question about the Overloading. Take the following function use as example:
f('a', 'a');
If we have two definition as:
static void f(int i, char j){
System.out.println("int_char");
}
static void f(double i, char j){
System.out.println("double_char");
}
It will be OK. Because all the second parameters are exactly matching. But the first parameters, they both use widen. And the widen order for char is:
char -> int -> long -> float -> double
For char to achieve int, it needs one step. But to achieve double, it will need 4 steps. So the result is:
int_char
But the I change the order of the paremeter as:
static void f(int i, char j){
System.out.println("int_char");
}
static void f(char i, double j){
System.out.println("char_double");
}
The compiler would propose an error as ambiguous. Why?
Another case is as following:
static void f(char i, Character j){
System.out.println("char_Character");
}
static void f(Character i, Character j){
System.out.println("Character_Character");
}
Both of the second parameters use atuoboxing. But the first parameter of void f(char i, Character j) is exactly matching. Why these two function together will lead to ambiguous?
Finally, if anyone of these functions appears with the follwing one:
static void f(Character... i){
System.out.println("Character_varargs");
}
The output is not Character_varargs, because widen > boxing > varargs. But when two ambiguous functions are with the Character_varargs one like:
static void f(char i, Character j){
System.out.println("char_Character");
}
static void f(Character i, Character j){
System.out.println("Character_Character");
}
static void f(Character... i){
System.out.println("Character_varargs");
}
The result would be Character_varargs. Why?
Even we add some non-ambiguous and higher-priority-in-overloading function like:
static void f(int i, char j){
System.out.println("int_char");
}
static void f(char i, double j){
System.out.println("char_double");
}
static void f(int i, double j){
System.out.println("int_double");
}
static void f(Character... i){
System.out.println("Character_varargs");
}
The result is still Character_varargs. Why? If only consider void f(int i, double j) and void f(Character... i), the output should be int_double.
When the compiler meet with ambiguous functions, does it directly "jump" to the varargs function (if there is) without considering any other candidate?
Thanks!
Upvotes: 4
Views: 2420
Reputation: 46
Widen > boxing > varargs is not exactly correct.
Appropriate is widen > boxing and unboxing > widen and boxing/unboxing and varargs all three.
In the third step all three are allowed.
static void f(int i, char j){
System.out.println("int_char");
}
static void f(double i, char j){
System.out.println("double_char");
}
In the above case you can "arrange" them in order of preference based on distance of widening on 1 particular arg. But below you can not arrange them.
static void f(int i, char j){
System.out.println("int_char");
}
static void f(char i, double j){
System.out.println("char_double");
}
Next question was
static void f(char i, Character j){
System.out.println("char_Character");
}
static void f(Character i, Character j){
System.out.println("Character_Character");
}
When boxing was needed to be allowed for matching, (as there was no match without boxing), all methods with or without boxing on first or second argument are treated at same preference. So the first is not better than the second, so we can not arrange them in preference order. Leads to ambiguous.
Now if below is also present,
static void f(Character... i){
System.out.println("Character_varargs");
}
As per rule, since no appropriate method was found (2 ambiguous were found) after boxing/unboxing so third step was needed with var args. Which finally finds the method to be resolved.
In the case below also we needed to go to third step, (widen and boxing/unboxing and varargs) to find a match
static void f(int i, char j){
System.out.println("int_char");
}
static void f(char i, double j){
System.out.println("char_double");
}
static void f(int i, double j){
System.out.println("int_double");
}
static void f(Character... i){
System.out.println("Character_varargs");
}
Refer to https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12
Upvotes: 2