下面的代码会产生语法错误:
方法
是不明确的f(int[])
对于类型C
我的代码:
public class C{
public static void f(int... i)
{
System.out.println("a");
}
public static void f(Integer... i)
{
System.out.println("b");
}
public static void main(String[] args) {
f(new Integer(2));
}
}
如果我使用数组表示法[]
而不是...
并使用f(new Integer[]{3,4,5})
正确调用函数,编译器可以正确地决定我要使用哪种方法。
编译器无法决定使用...
调用哪个函数的原因是什么?
答案 0 :(得分:2)
在JLS, Secion 15.12, "Method Invocation Expressions"中解释了为特定调用站点查找“正确”方法的过程。经过基本完整性检查的简短序言后,相关部分从section 15.12.2.1, Identify Potentially Applicable Methods开始。在您的情况下,根据此定义,两种方法都可能适用。
后续流程包括三个阶段。在您的情况下,该方法是变量arity 方法(由于“varargs”)。所以它立即从15.12.2.4, Phase 3: Identify Applicable Variable Arity Methods开始。
当且仅当满足以下所有条件时,方法m才是适用的变量方法:
- 对于1≤i<1。 n,ei的类型Ai可以通过方法调用转换为Si来转换。
- ...
(其他条件与此无关)
Method Invocation Conversion (JLS, 5.3)允许以下转换:
从Integer
到Integer
的转换是身份转换(第一个要点)。从Integer
到int
的转换是一个拆箱转换(最后一个要点)。
因此,根据规范,这两种方法都是“适用的变量方法”。
答案 1 :(得分:0)
规则为WBV/WAV
加宽 - &gt; (自动)拳击 - &gt;在方法重载的情况下,Varargs 。
拓宽
int -> long -> float -> double
拳击
Integer -> Number -> Object
a)扩大Varargs
int... -> long... -> float... -> double...
b)拳击然后Varargs
Integer... -> Number... -> Object...
换句话说
Varargs [Last option]
^
|
Boxing [Newer style, added in Java 1.5]
^
|
Widening [Older style, choosen by the compiler to support existing code]
注意:强>
Boxing
然后也允许Widening
。Varargs
然后不允许Boxing
。Varargs
被视为Widening
和boxing
Widening then Varargs
或Boxing then Varargs
。如果两种可能性都存在,则会导致模糊方法调用。 f(new Integer(2))
案例中的转化。根据规则Boxing
,然后Widening
Integer -> Number -> Object -> int -> long -> float -> double
现在double
3.a)扩大Varargs(int...
)
3.b)拳击然后Varargs(Integer...
)
但两者都存在,因此导致不明确的方法调用。
f(new Integer[]{3,4,5})
Integer...
是直接匹配。 Varargs
然后不允许Boxing
。
答案 2 :(得分:0)
Varargs
和Boxing
都是在Java 5中引入的。随着Java 5出现了处理遗留代码的问题,其中编译器执行了扩展操作(例如,在有很长的情况下,编译器会选择长于整数,因为在Java 5之前允许将操作从int扩展到long,但由于varargs和Boxing处于同一级别(Java 5以后),编译器无法确定正确的类型。只需删除varargs并替换为数组,它会工作正常
Varargs和Boxing / Unboxing在组合使用时没有明确的偏好
答案 3 :(得分:-2)
......适用于可变数量的参数。你必须传递像f(1,2,3)这样的值,这就是错误的原因。