I have read the fact that in method overloading , Priority goes as:
Exact Match>widening>boxing/unboxing>varargs
This works great for functions having only one argument. But for functions having more than one argument this sometimes give strange results, presumably because I am not able to apply this rule correctly.
For example:
Code 1:
public static void overloadResolve(long i,int j){} //1
public static void overloadResolve(int i,Integer o){} //2
overloadResolve(5,6); // calls 1
Code 2:
public static void overloadResolve(int i,int... j){} //1
public static void overloadResolve(Integer i,long o){} //2
overloadResolve(5,6); // calls 2
Can you explain how to deal with multiple argument functions in the case of overloading?
Well, in the first case, the first method has one parameter that requires widening and another that is exact match. The second method has one parameter with exact match and another that requires boxing. Since widening has precedence over boxing, the first method is chosen.
In the second case the first method has varargs, while the second requires boxing and widening. Since both widening and boxing have precedence over varargs, the second method is chosen.
You could come up with examples where it wouldn't be clear which method to choose :
public static void overloadResolve(long i,Integer j){} //1
public static void overloadResolve(Integer i,long o){} //2
overloadResolve(5,6);
In this case the first method has precedence for the first argument, while the second method has precedence for the second argument. Therefore the compiler can't choose between them, and compilation would fail.
In your second case, since the last priority is varargs, before that it passes Auto Boxing(int to Integer-first argument) and Widening for second argument (int to long). Where as varargs in last priority it chooses call 2
.
As you said, the priority order is exact match>widening>boxing/unboxing>varargs. Here is what Java will do whith you example:
public static void overloadResolve(long i,int j){} //1
public static void overloadResolve(int i,Integer o){} //2
overloadResolve(5,6);
- There is not function
overloadResolve(int, int)
so no exact match.
- Widening
int i
in to long i
matches overloadResolve(long i,int j)
, let's call it !
Example 2:
public static void overloadResolve(int i,int... j){} //1
public static void overloadResolve(Integer i,long o){} //2
overloadResolve(5,6);
- There is not function
overloadResolve(int, int)
so no exact match.
- Widening second arg
int i
in to long i
and Boxing first arg int i
into Integer i
matches public static void overloadResolve(Integer i,long o)
, let's call it !
So basically, you can apply the priority order for every argument until it matches the signature of one of the overloads.
Overloaded method selection process in Java have been defined in details here: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 and states:
(...) uses the name of the method and the types of the argument expressions to
locate methods that are both accessible and applicable, that is,
declarations that can be correctly invoked on the given arguments.
There may be more than one such method, in which case the most specific one is chosen.
Without going through in-depth details, the statement most specific one is chosen
in your case boils down to:
1. For all parameters identify their respective priority in method signature (based on the order you've defined)
2. Choose lowest priority out of them for every method.
3. Method with the highest resulting priority will be applied.
Lets see how it works for the codes you've shown:
overloadResolve(5,6); //Call with (int, int)
CODE1:
//(widening, exact) -> lowest priority: widening
public static void overloadResolve(long i,int j){}
//(exact, autoboxing) -> lowest priority: autoboxing
public static void overloadResolve(int i,Integer o){}
Since highest priority is widening, first method is chosen
CODE2:
//(exact, vararg) -> lowest: vararg
public static void overloadResolve(int i,int... j){}
//(autoboxing, widening) -> lowest: autoboxing
public static void overloadResolve(Integer i,long o){}
Since highest available priority is widening, second method is chosen.