为什么这不会产生歧义?

Why does this not produce an ambiguity?

我刚刚写了一些具有以下结构的代码:

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

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

我很惊讶这个编译,如果我调用

method(3);

然后它会选择第一个。显然,这在某种意义上是自然而然的选择,但如果第一种方法不存在,这将是调用第二种方法的合理方式(使用空可变参数数组)。所以它肯定应该被认为是模棱两可的并产生编译时错误?

还是说这是特例?

这样对待它似乎是错误的,因为这意味着添加新方法可能会破坏现有代码,这可不是什么好事。

(如果第一个被添加为包含第二个的子类的新方法,天知道你最终会调用哪个...)

第一种方法的参数类型是

int x

第二种方法的参数类型是

int x, String[] things

因此这两个方法 not 具有相同的签名并且没有歧义。 @Glorfindel 解释了 Java 如何决定调用哪个方法,但是如果你想在没有任何 things 的情况下调用第二个方法,你可以传入一个空数组。

method(6, new String[0]);

根据Java语言规范的Chapter 15,搜索适用的方法分三个阶段进行。

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.

所以,第一种方法在第一阶段已经可以使用了。其余阶段被跳过; String... 方法只会在第三阶段被考虑:

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