Ramses Ramses - 3 months ago 12
Java Question

Constructor ambiguity with varargs in java 8

In the class below, I get a compilation error with java 8 due to an ambiguous call to this(). With java 6 this class compiled fine though.
I know I could refactor this using factory methods and such but for the actual class where the problem occurs, I would strongly prefer to maintain the current API for now.

Can anyone think of a way to resolve the ambiguity without changing the external API?

public class Vararg8 {

public Vararg8(final Object... os) {}

public Vararg8(final boolean b,
final String s,
final int... is) {}

public Vararg8() {
this(true, "test", 4, 5, 6);
}
}

Answer

You can do it by passing an explicit int[] array:

public Vararg8()
{
  this(true, "test", new int[]{4, 5, 6});
}

You might notice that this is still, in one sense, ambiguous: what you've passed is still compatible with the Object... constructor. The reason this works is that method resolution goes in various stages, and only the last stage allows consideration of varargs parameters. Because you've used an explicit array, it hits the second one fine without needing varargs expansion. It can't hit the first one without varargs expansion, so that wouldn't be considered till the final stage.

See the appropriate JLS docs:

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.

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