为什么此代码中没有编译错误:
public class OverloadingVarArgs
{
public void fun1(int... b)
{
System.out.println("int");
}
public void fun1(long... a)
{
System.out.println("long");
}
public static void main(String[] args)
{
OverloadingVarArgs obj = new OverloadingVarArgs();
obj.fun1();
}
}
但是这段代码给出了编译错误!
public class OverloadingVarArgs
{
public void fun1(int... b)
{
System.out.println("int");
}
public void fun1(boolean... a)
{
System.out.println("boolean");
}
public static void main(String[] args)
{
OverloadingVarArgs obj = new OverloadingVarArgs();
obj.fun1();
}
}
我认为在这两种情况下都应该存在编译错误,但事实并非如此。
答案 0 :(得分:9)
选择正确的重载方法的规则如下:
看看最后一条规则。您可以不将扩展或装箱与可变长度参数组合使用。这意味着不能以任何方式操纵类型,您必须按原样执行比较。可以比较int
和long
,没问题,编译器可以推断int
是两者中较小的一个。按照第一条规则,它将使用最小的方法参数,因此它已经计算出一个方法的正确(和唯一)路径。
但是,当你到达boolean
和int
时,由于Java的强类型,两者之间不存在比较方法。由于不知道哪种类型最小,编译器完全不知道你指的是哪种方法。
更多视觉示例
让我们从编译器的角度一步一步地看待它。首先,使用int
和long
。
int和long
步骤1 - 检查参数是否与任何参数匹配,如果是,那么它与哪个参数完全匹配
好吧,varargs
表示您可以将0
传递给多个参数。在这种情况下,您已选择传递0
个参数,因此您的通话符合int
类型和long
类型。
第2步 - 尝试自动装箱或加宽。这应该有助于确定哪一个
您正在使用varargs,因此编译器知道根据最终规则它无法执行此操作。
第3步 - 尝试确定哪种类型最小
编译器能够将类型int
与类型long
进行比较。由此可知,int
是最小的类型。
第4步 - 拨打电话
知道int
是最小的类型,然后它将值传递给方法执行。
好的,现在让我们对boolean
和int
做同样的事情。
布尔和int
步骤1 - 检查参数是否与任何参数匹配,如果是,那么它与哪个参数完全匹配
同样的故事。你没有通过任何东西,所以匹配两个参数。
第2步 - 尝试自动装箱或加宽。这应该有助于确定哪一个
如上所述,由于您使用了varargs,因此不允许这样做。
第3步 - 尝试确定哪种类型最小
这是至关重要的区别。这里的类型不可比较。这意味着编译器不知道您希望通过最小类型的参数或调用哪个方法。因此,它无法找到正确的路线。
第4步 - 拨打电话
如果不知道要调用哪个方法,它就无法继续执行并抛出相应的异常。
答案 1 :(得分:5)
在第二个示例中,编译器无法确定要调用的最具体的方法。
血腥细节在the language spec中解释,但基本上如果比较两个变量(var-arg)方法,那么如果方法A可以接受传递给方法B的参数,而不是其他方式周围,然后方法B是最具体的。
在您的第一个示例中,应用rules of primitive sub-typing,即:
double> 1 float
浮动> 1 long
long> 1 int
int> 1 char
int> 1 short
短> 1 字节
(其中> 1 表示'的直接超类型)
我们可以看到int
比long
更具体,因此选择了fun1(int... b)
方法。
在第二个示例中,编译器在int
和boolean
之间进行选择。这些原始类型之间没有子类型关系,因此没有最具体的方法,“方法调用不明确,发生编译时错误。”(15.12.2.5中的最后一行) )。
答案 2 :(得分:4)
当您拥有int
和long
(可比类型)时,默认情况下将使用最小值,即int
(因为您没有传递参数) - 我认为这是因为int
可以扩展到long
但long
不能(除非你显式强制转换它) ,编译器将选择最低精度类型。
但是当你有boolean
和int
时,无法进行比较并且你会得到
The method fun1(int[]) is ambiguous for the type OverloadingVarArgs