1

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.

Code Complete
  • 3,146
  • 1
  • 15
  • 38
  • @ GhostCat says Reinstate Monica - I just finished correcting this. Sorry! I didn't expect myself the image would look so ugly, so I typed it even before saw your comment. Anyway, the image looked nasty, I do agree. – Code Complete Oct 25 '19 at 14:27
  • GhostCat says Reinstate Monica - I understood and I will keep this in mind in the future. Initially I copied the image from my book, not my IDE, to save time. But I see your point and fully agree. I felt like doing something wrong myself :) Thanks a lot again! – Code Complete Oct 25 '19 at 14:41
  • 1
    Did you look at this one? The answer by Eran seems pertinent to your question as it explains why, indeed, Step 3 is attempted: https://stackoverflow.com/questions/27874380/ambiguous-varargs-methods – NorthernSky Oct 25 '19 at 15:10

2 Answers2

3

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.

Aaron
  • 24,009
  • 2
  • 33
  • 57
0

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.

Code Complete
  • 3,146
  • 1
  • 15
  • 38