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);
}
}
There can be only one variable argument in a method. Variable argument (Varargs) must be the last argument.
There can be only one variable argument in the method. Variable argument (varargs) must be the last argument.
Varargs is a short name for variable arguments. In Java, an argument of a method can accept arbitrary number of values. This argument that can accept variable number of values is called varargs. The syntax for implementing varargs is as follows: accessModifier methodName(datatype… arg) { // method body }
Sometimes unexpected errors can result when overloading a method that takes a variable length argument. These errors involve ambiguity because both the methods are valid candidates for invocation. The compiler cannot decide onto which method to bind the method call.
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.
Try this:
public Vararg8()
{
this(true, "test", new int[]{4, 5, 6});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With