编译器错误:对调用不明确的引用 [英] Compiler error : reference to call ambiguous
问题描述
案例 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
案例 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);
}
显示编译错误调用模棱两可的引用
.但是,我无法理解.为什么 ?但是,当我从 Case 2
中注释掉任何 call()
方法时,它工作正常.谁能帮我理解,这里发生了什么?
Shows compilation error reference to call ambiguous
. But, I was unable to understand. Why ? But, when I commented out any of the call()
methods from Case 2
, then It works fine. Can anyone help me to understand, what is happening here ?
推荐答案
在 Java 语言规范 (JLS) 中以非常正式的方式定义了查找最具体的方法.我在下面提取了适用的主要项目,同时尽量删除了正式的公式.
Finding the most specific method is defined in a very formal way in the Java Language Specificaion (JLS). I have extracted below the main items that apply while trying to remove the formal formulae as much as possible.
总的来说,适用于您的问题的主要项目是:
In summary the main items that apply to your questions are:
- JLS 15.12.2:您的用例属于第 3 阶段:
- JLS 15.12.2: your use case falls under phase 3:
第三阶段(第 15.12.2.4 节)允许将重载与可变数量方法、装箱和拆箱相结合.
The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.
- 然后 JLS 15.12.2.4 基本上确定这两种方法都适用,因为 10 可以转换为
Integer...
或int...
.到现在为止还挺好.该段落的结论是: - Then JLS 15.12.2.4 basically determines that both method are applicable, because 10 can be converted to both an
Integer...
or anint...
. So far so good. And the paragraph concludes: - 这让我们看到 JLS 15.12.2.5.本段给出了一个元数方法
m(a...)
比另一个元数方法m(b...)
更具体的条件.在您使用一个参数而没有泛型的用例中,它归结为: - Which brings us to JLS 15.12.2.5. This paragraph gives the conditions under which an arity method
m(a...)
is more specific than another arity methodm(b...)
. In your use case with one parameter and no generics, it boils down to: - 如果所有最大的特定方法都具有覆盖等效(第 8.4.2 节)签名 [...] => 不是您的情况,因为不涉及泛型并且 Integer 和 int 是不同的参数
- 否则,我们说方法调用不明确,会出现编译时错误.
在适用的可变元方法中选择最具体的方法(第 15.12.2.5 节).
The most specific method (§15.12.2.5) is chosen among the applicable variable-arity methods.
m(a...)
比 m(b...)
更具体 iif a <: b
,其中<:
表示是
的子类型.
m(a...)
is more specific thanm(b...)
iifa <: b
, where<:
meansis a subtype of
.
碰巧int
不是Integer
的子类型,Integer
也不是int
的子类型.
It happens that int
is not a subtype of Integer
and Integer
is not a subtype of int
.
为了使用 JLS 语言,两个 call
方法因此是最具体的(没有方法比另一个更具体).在这种情况下,同一段落的结论是:
To use the JLS language, both call
methods are therefore maximally specific (no method is more specific than the other). In this case, the same paragraph concludes:
注意
例如,如果您将 Integer...
替换为 long...
,您将拥有 int <: long
和最具体方法是 call(int...)
*.
同样,如果将 int...
替换为 Number...
,call(Integer...)
方法将是最具体的.
If you replaced Integer...
by long...
for example, you would have int <: long
and the most specific method would be call(int...)
*.
Similarly, if you replaced int...
by Number...
, the call(Integer...)
method would be the most specific.
*实际上 Java 7 之前的 JDK 中存在一个错误在这种情况下调用.
这篇关于编译器错误:对调用不明确的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!