我不明白为什么在这里的情况1,它没有给出编译错误,相反在情况2(varargs),它给出了编译错误。任何人都可以详细说明编译器在这两种情况下的差异吗?我经历过很多关于它的帖子,但还不能理解它。
案例#1
public class Test {
public void display(int a) {
System.out.println("1");
}
public void display(Integer a) {
System.out.println("2");
}
public static void main(String[] args) {
new Test().display(0);
}
}
输出为: 1
案例#2
public class Test {
public void display(int... a) {
System.out.println("1");
}
public void display(Integer... a) {
System.out.println("2");
}
public static void main(String[] args) {
new Test().display(0);
}
}
编译错误:
The method display(int[]) is ambiguous for the type Test
答案 0 :(得分:5)
在第一个示例中,在严格的调用上下文中调用display(int)
方法,而在松散的调用上下文中调用display(Integer)
(因为需要自动装箱)。因此编译器根据JLS选择display(int)
方法。调用上下文在此处解释JLS 5.3. Invocation Contexts
在第二个示例中,在松散调用上下文中调用这两个方法,因此编译器需要找到最具体的方法JLS 15.12.2.5 Choosing the Most Specific Method。由于int不是Integer的子类型,因此没有最具体的方法,编译器会抛出编译错误。
您可以在Method overload ambiguity with Java 8 ternary conditional and unboxed primitives
找到类似编译错误的解释适用于此案例的部分:
确定适用的方法分为3个阶段。
第一阶段(§15.12.2.2)在没有的情况下执行重载决策 允许装箱或拆箱转换,或使用变量 arity方法调用。如果没有找到适用的方法 这个阶段然后处理继续到第二阶段。
第二阶段(§15.12.2.3)执行重载解析 允许装箱和拆箱,但仍然排除使用 变量arity方法调用。如果没有找到适用的方法 在这个阶段,然后处理继续到第三阶段。
第三阶段(§15.12.2.4)允许重载与 变量arity方法,装箱和拆箱。
对于第一个示例,只有display(int)
方法在第一个阶段匹配,因此选择它。对于第二个示例,两个方法在第三阶段匹配,因此选择最具体方法算法发挥作用JLS 15.12.2.5 Choosing the Most Specific Method:
m2不是通用的,m1和m2适用于变量arity 调用,以及m1的第一个k变量arity参数类型 是S1,...,Sk和m2的第一个k变量arity参数类型 是T1,...,Tk,Si的类型比参数ei的Ti更具体 对于所有i(1≤i≤k)。另外,如果m2有k + 1个参数,那么 m1的第k + 1个可变arity参数类型是该类型的子类型 k + 1的可变参数类型m2。
如前所述,由于int&lt ;: Integer不满足,因此没有最具体的方法。
答案 1 :(得分:-1)
在Java Version 1.5之后,引入了一个名为autoboxing
的酷炫功能,它使编译器能够将原始类型转换为 Wrapper Type 。因此,在编译期间,这两种方法都是一样的。
public void display(int... a) {
System.out.println("1");
}
public void display(Integer... a) {
System.out.println("2");
}
由于autoboxing
在编译期间执行,因此该函数将被视为同一方法。所以在Java中重载方法时要小心 Autoboxing 。
你在这里找到的更多......