1

So, today I've been testing Java's overloading techniques and I've come across ambiguity which I can't explain. Basically, when there is a vararg method with primitive and its corresponding wrapper the compiler complains and can't decide which one to choose and I don't understand why? It's easy for human to decide and not for compiler?

Here is the fragment which works for non-vararg parameters:

public static void main(String[] args)
{
    int a = 14;
    Integer b = new Integer(14);
    stuff(a);
    stuff(b);
}

static void stuff(Integer arg) { System.out.println("Integer"); }
static void stuff(int arg) { System.out.println("int"); }

And here comes the vararg which complains and cries like a baby:

public static void main(String[] args)
{
    int a = 14;
    Integer b = new Integer(14);
    stuff(a); // Doesn't compile (ambiguity)
    stuff(b); // Doesn't compile (ambiguity)
}

static void stuff(int... arg) { System.out.println("varargs int"); }
static void stuff(Integer... arg) { System.out.println("varargs Integer"); }
4
  • 2
    Because of autoboxing, so in practice those two methods are actually the same. Commented Mar 13, 2017 at 10:03
  • 2
    Because of autoboxing, Java knows that if you pass ints to the function, they could be converted to Integers. However, that means that both method are candidates. As humans we're better and know which is the most likely. Commented Mar 13, 2017 at 10:04
  • No, sorry, I think that's not enough. Inside of stuff(int... arg) arg has the type int[], so why should the parameters be converted to Integer? Commented Mar 13, 2017 at 10:40
  • See here for a deeper explanation: stackoverflow.com/questions/36384527/… Commented Mar 13, 2017 at 11:56

2 Answers 2

3

Consider the following two hypothetical calls to stuff():

int a = 14;
Integer b = new Integer(14);

stuff(a, b);
stuff(b, a);

How does the compiler even know which method should be called here? Because of autoboxing rules, either call could be referring to either overloaded method.

Update:

My answer is logically correct, or at least on the right track, but for a more formal answer we can refer to this SO question:

Why ambiguous error when using varargs overloading with primitive type and wrapper class?

The two varargs method are invoked in loose invocation context. As a result, the compiler will attempt to find the more specific method via JLS 15.12.2.5 Choosing the Most Specific Method. However, since neither int nor Integer are subtypes of one another, the compiler will throw an error.

Sign up to request clarification or add additional context in comments.

1 Comment

But he did not call the method with two parameters. While in that case it would surely be ambigous, I think in this case it is not obvious.
3

The problem is:

java is doing behind the scenes bridge methods (you need to verify that is you need deep info)

AND the important part, vargargs means too YOU CAN JUST NOT PASS ANY PARAMETER, so:

static void stuff(int... arg)   

and

static void stuff(Integer... arg) 

can both being invoked taking no parameters... so that will create some conflict about what method should the JVM invoke

3 Comments

Well, is that because of autoboxing or because of this, or are those 2 reasons tied together in this case?
I created two methods named check, one with argument String... the other one with Integer... and it compiles (unless I actually call it with no arguments, then it doesn't compile)
@Whatzs It won't compile if you pass them null too. In that case you need to cast null to the correct type to tell the compiler which method you want to call: check((Integer) null)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.