I feel that these are applicable:
JLS 15.12.2.4. Phase 3: Identify Methods Applicable by Variable Arity Invocation
JLS 15.12.2.5. Choosing the Most Specific Method
But JLS language is so complex that I cannot understand the point.
void f(Integer... arg) { System.out.println("Integer..."); }
void f(int... arg) { System.out.println("int..."); }
void test() {
f((short)1); // int... called
f(1); // c.ERR
I seemingly understand that one (besides this was ALREADY ANSWERED here), though the answer did not describe all the details (the exact sequence - what arguments are tried) of the entire overload resolution process - anyway my question is mainly in the second code snippet (int.. vs long...). But let me go into details of the above snippet:
f((short)1)
- no exact match, so primitive short is first widened (no match found), then short is boxed into Short (no exact match found), Short is widened (Number, Object) - no match, now comes the third phase (varargs) => the following is tried:
- short... (no exact match => try primitive widening)
- int... (exact match found, but don't stop, search further!)
- long..., float..., double... (no match => try boxing)
- Short..., Number..., Object...
As no other match found - it compiles OK.
f(1)
- no exact match, so primitive int is first widened (no match found), then int is boxed into Integer (no exact match found), Integer is widened (Number, Object) - no match, now comes the third phase (varargs) => the following is tried:
- int... (exact match found, but don't stop, search further!)
- long..., float..., double... (no match => try boxing)
- Integer... (now ambiguous), Number..., Object...
As two possible matches found - we have a compile Error.
void f(long... arg) { System.out.println("long..."); }
void f(int... arg) { System.out.println("int..."); }
void test() {
f((byte)1); // int... called
f(1); // int... called
}
f(byte)
- as comes the third phase (varargs) => the following is tried:
- byte... (no match => try primitive widening)
- short..., int... (match found, but look further), long... (shall be ambigouos error, but it is not!), float..., double... (now also do boxing with subsequent reference widening to look for more possible matches to flag compile error "ambiguous")
- Byte..., Number..., Object...
As two possible matches found - shall be a compile Error (but it is not).
My guess is that there are 4 procedures (exact primitive match, primitive widening, boxing and exact reference match, reference widening) and the compiler stops if it found a match during some procedure (the procedure is not continued), but tries all other subsequent procedures. In this case compiler stopped at procedure 2 (only int... matches, but not long...), procedures 3 and 4 yielded no match.
The above-quoted answer on SO offers the following criteria:
for one parameter to be more specific than the other, the type of that parameter must be a subtype of the other method's parameter.
It may work for reference types, but not in case of primitives.
I seem to understand 15.12.2. Compile-Time Step 2: Determine Method Signature. But in my case we have "The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing." - but the detailes of this is the problem.