【问题标题】:Why does this not produce an ambiguity? [duplicate]为什么这不会产生歧义? [复制]
【发布时间】:2016-04-13 20:32:59
【问题描述】:

我刚刚写了一些结构如下的代码:

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

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

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

method(3);

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

或者这是否被视为特殊情况?

这样对待它似乎是错误的,因为这意味着添加一个新方法可能会破坏现有代码,这不是一个非常愉快的事情。

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

【问题讨论】:

  • 你调用了一个有1个参数的方法,为什么它会调用一个需要2个参数的方法?
  • @loli 因为没有一个需要两个。第二个有一个可变参数,这意味着String... 部分可以接受任意数量的参数,包括零。
  • @chiastic-security 啊我不知道那是Java等价物,我以为你写的......因为你懒得在键盘上找到[]
  • vararg 方法是在 java5 中引入的比较晚。他们不希望现有代码受其影响,因此在方法解析期间可变参数方法的优先级较低。

标签: java overloading javac variadic-functions ambiguous-call


【解决方案1】:

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

第一阶段(第 15.12.2.2 节)执行重载决议,不允许装箱或拆箱转换,或使用变量 arity 方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。

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

第三阶段(第 15.12.2.4 节)允许将重载与可变参数方法、装箱和拆箱相结合。

【讨论】:

    【解决方案2】:

    第一个方法的参数类型是

    int x
    

    第二种方法的参数类型是

    int x, String[] things
    

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

    method(6, new String[0]);
    

    【讨论】: