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(使用前将#替换为@)