7

I just wrote some code with the following structure:

public void method(int x) {
    //...
}

public void method(int x, String... things) {
    //...
}

I was rather surprised that this compiled, and that if I invoked

method(3);

then it would pick the first one. Obviously this is in some sense the natural one to pick, but if the first method didn't exist, this would be a reasonable way of invoking the second (with an empty varargs array). So surely it should be considered ambiguous and produce a compile-time error?

Or is this treated as a special case?

It seems wrong to treat it as such, because it means that adding a new method could break existing code, and that is not a very happy state of affairs.

(Goodness only knows which one you'd end up invoking if the first one were added as a new method of a subclass containing the second one...)

brso05
  • 13,142
  • 2
  • 21
  • 40
chiastic-security
  • 20,430
  • 4
  • 39
  • 67
  • You called a method with 1 parameter,why would it call the one with 2 needed? – loli Aug 12 '15 at 14:20
  • 2
    @loli because there isn't one with two needed. The second has a varargs parameter, which means that the `String...` part can take any number of arguments, including zero. – chiastic-security Aug 12 '15 at 14:30
  • @chiastic-security Ah I didn't know that was the Java equivalent, I thought you wrote ... because you were too lazy to find [] on the keyboard – loli Aug 12 '15 at 14:33
  • vararg methods was introduced rather late in java5. they don't want existing code affected by it, therefore vararg methods are put in a low priority during method resolution. – ZhongYu Aug 12 '15 at 17:12

2 Answers2

10

According to Chapter 15 of the Java Language specification, the search for an applicable method is done in three phases.

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.

So, the first method is considered applicable in the first phase already. The rest of the phases are skipped; the String... method would only be considered in the third phase:

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

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
0

The argument type of the first method is

int x

The argument types of the second method are

int x, String[] things

Therefore the two methods do not have the same signature and there is no ambiguity. @Glorfindel explains how Java decides which method to invoke, but if you wanted to invoke the second method without any things, you can pass in an empty array.

method(6, new String[0]);
Samuel
  • 16,923
  • 6
  • 62
  • 75