编译器错误:引用调用模糊

Rav*_*avi 24 java methods polymorphism boxing java-7

情况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);
}
Run Code Online (Sandbox Code Playgroud)

案例1的输出:hello10

案例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);
}
Run Code Online (Sandbox Code Playgroud)

显示编译错误reference to call ambiguous.但是,我无法理解.为什么?但是,当我评论出任何call()方法时Case 2,它的工作正常.任何人都可以帮助我理解,这里发生了什么?

ass*_*ias 14

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

总之,适用于您的问题的主要项目是:

第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合.

  • 然后JLS 15.12.2.4基本上确定两种方法都适用,因为10可以转换为a Integer...或a int....到现在为止还挺好.该段的结论是:

在适用的变量方法中选择最具体的方法(第15.12.2.5节).

  • 这将我们带到JLS 15.12.2.5.本段给出了arity方法m(a...)比另一种arity方法更具体的条件m(b...).在具有一个参数且没有泛型的用例中,它归结为:

m(a...)m(b...)iif 更具体a <: b,<:意味着什么is a subtype of.

它发生int是不是一个亚型IntegerInteger是不是一个亚型int.

因此,要使用JLS语言,这两种call方法都是最具体的(没有哪种方法比另一种方法更具体).在这种情况下,同一段落总结如下:

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

注意

如果更换Integer...long...,例如,你必须int <: long和最具体的方法是call(int...)*.
同样,如果替换int...Number...,则该call(Integer...)方法将是最具体的.

*在Java 7之前的JDK中实际上存在一个错误,在这种情况下会显示一个模糊的调用.