javaoverloadingambiguity

Java varargs method overloading compiler error - ambiguity?


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"); }

Solution

  • 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.