Code Complete
Code Complete

Reputation: 3206

Detailed procedure (steps) during argument matching for overloaded methods invocation

Why is (2) c.ERR (ambiguous)? First method argument - char ('a') is widened to float => match.

If match is found, no need to proceed to Step 2 (boxing/unboxing) or Step 3 (trying vararg)? Or I missed sth in JLS and Step 2 and Step 3 are attempted?

void f(float f, Character... args) {

}

void f(Character... args) {

}


f(1, 'a'); // OK - void f(float f, Character... args) chosen

f('a', 'b'); // c.ERR - ambiguous

1 is OK

2 is c.ERR - ambiguous.

P.S. I found this in JLS (15.12.2.) and this on SO, but it didn't help me.

Upvotes: 1

Views: 80

Answers (2)

Code Complete
Code Complete

Reputation: 3206

As per JLS (§15.12.2)

The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

This ensures that a method is never chosen through variable arity method invocation if it is applicable through fixed arity method invocation.

The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

In our case third phase is applied:

All these steps below tried (even if a match found, next step is tried further!!!)

  1. First argument (primitive) widening (see if widened type is same as vararg type)
  2. First argument boxing (see if boxed type is same as vararg type)
  3. First argument boxing and then widening reference (not sure)?

Plus, for every step above, same 3 steps are performed for the second argument (making it 3*3 = 9 different paths-attempts).

If more than one methods are found, most specific is chosen: f(Integer) is more specific than f(Number) for f(2) call. Usually most specific means that arguments are in a hierarchy.

In our case both methods are chosen and the arguments are not in any hierarchy to find a more specific method. This causes ambiguity.

Upvotes: 0

Aaron
Aaron

Reputation: 24812

The int 1 can be widened to float, but it can't be boxed to Character, so only the void f(float, Character...) method signature is applicable.

The char 'a' however can both be widened to float and boxed to Character, so the loose invocation conversion context finds that both method signatures are applicable. Note that the strict invocation context that is attempted before the loose one cannot find any applicable signature because while it tries widening primitives, it isn't allowed to box them.

Upvotes: 3

Related Questions