编译器错误:对调用的引用不明确

2024-04-19

Case 1

static void call(Integer i) {
    System.out.println("hi" + i);
}

static void call(int i) {
    System.out.println("hello" + i);
}

public static void main(String... args) {
    call(10);
}

案例 1 的输出:hello10

Case 2

static void call(Integer... i) {
    System.out.println("hi" + i);
}

static void call(int... i) {
    System.out.println("hello" + i);
}

public static void main(String... args) {
    call(10);
}

显示编译错误reference to call ambiguous。但是,我无法理解。为什么 ?但是,当我注释掉任何call()方法来自Case 2,然后就可以正常工作了。谁能帮助我理解这里发生了什么?


Java 语言规范 (JLS) 中以非常正式的方式定义了查找最具体的方法。我在下面提取了在尝试尽可能删除正式公式时适用的主要项目。

总之,适用于您的问题的主要内容是:

  • JLS 15.12.2 http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2:您的用例属于第三阶段:

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

  • Then JLS 15.12.2.4 http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.4基本上确定这两种方法都适用,因为 10 可以转换为Integer... or an int...。到目前为止,一切都很好。该段落的结论是:

最具体的方法(第 15.12.2.5 节)是在适用的可变数量方法中选择的。

  • 这让我们想到JLS 15.12.2.5 http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5。本段给出了 arity 方法的条件m(a...)比其他 arity 方法更具体m(b...)。在只有一个参数且没有泛型的用例中,它可以归结为:

m(a...)比更具体m(b...) iif a <: b, where <: means is a subtype of.

碰巧的是int不是 的子类型Integer and Integer不是 的子类型int.

要使用 JLS 语言,call因此,方法是最具体的(没有一种方法比另一种方法更具体)。在这种情况下,同一段的结论是:

  • 如果所有最大特定方法都具有等效覆盖(第 8.4.2 节)签名 [...]=> 不是你的情况,因为不涉及泛型,并且 Integer 和 int 是不同的参数
  • 否则,我们说方法调用是不明确的,并且会发生编译时错误。

NOTE

如果你更换了Integer... by long...例如,你会有int <: long最具体的方法是call(int...)*.
同样,如果你替换了int... by Number..., the call(Integer...)方法将是最具体的。

*实际上有Java 7 之前的 JDK 中存在一个错误,在这种情况下会显示不明确的调用 https://stackoverflow.com/questions/13524166/overload-function-int-and-long-simultaneously.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编译器错误:对调用的引用不明确 的相关文章

随机推荐