8

I have a question related to the following code snippet:

    class VarArgsTricky {
    static void wide_vararg(long... x) {
        System.out.println("long...");
    }

    static void wide_vararg(Integer... x) {
        System.out.println("Integer...");
    }

    public static void main(String[] args) {
        int i = 5;
        wide_vararg(i, i, i); // needs to widen and use var-args
        Long l = 9000000000l;
        wide_vararg(l, l); // prints sucessfully "long..."
    }
}

The first call to wide_vararg fails to compile(saying that the method is ambigous) while the second compiles just fine.

Any explanations about this behaviour? Thanks!

Ariel Chelsău
  • 959
  • 3
  • 9
  • 20
  • If this isn't just an experiment about overloading, please read Effective Java SE: Item 41 Use overloading judiciously. – TJR Oct 08 '11 at 21:37
  • This was purely an experiment, just to settle a potential question for OCPJP certification exam. – Ariel Chelsău Oct 09 '11 at 19:29

2 Answers2

10

The first wide_vararg call is ambiguous because the compiler could either:

  • widen the ints to longs, and call the first wide_vararg method, or
  • autobox the ints to Integers, and call the second wide_vararg.

It doesn't know which it should do, however, so it refuses to compile the ambiguous method call. If you want the first call to compile, declare i as an Integer or a long, not an int.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    According to K&B SCJP 6 book widening beats boxing while boxing beats var-args. So the first call should choose to widen rather than autobox. If i is declared as an Integer it doesn't compile either. Of course, long works. The question still remains: why doesn't it choose widening over autoboxing? – Ariel Chelsău Oct 03 '11 at 17:19
  • Hm, you're right. I'm not yet sure why. Heck, it could be a compiler bug. Whether or not varargs is beaten by widening or boxing is a non-question, though, since there is no non-varargs choice. – Matt Ball Oct 03 '11 at 17:43
  • 1
    There's no non-varargs choice, that's true. It could be some sort of compiler bug or some poorly known feature. It would be interesting to know exactly. – Ariel Chelsău Oct 03 '11 at 17:51
  • Related: http://stackoverflow.com/questions/2521293/bug-with-varargs-and-overloading – Matt Ball Oct 03 '11 at 18:49
1

When a var-arg method is invoked, the parameters get converted into an array of that type at compile time.

In the first call, the parameters get converted to an int[]. As all arrays in Java are direct sub types of the Object class, the concept of primitive widening does not apply in which case, both the overloads become equally applicable because long[] and Integer[] are at the same level. Hence the ambiguity