为什么此代码中没有编译错误:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码给出了编译错误!
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();
}
}
Run Code Online (Sandbox Code Playgroud)
我相信在这两种情况下应该存在编译错误,但事实并非如此.
选择正确重载方法的规则如下:
看看最后一条规则.您不能将扩展或装箱与可变长度参数组合使用.这意味着不能以任何方式操纵类型,您必须按原样执行比较.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.
boolean和int
步骤1 - 检查参数是否与任何参数匹配,如果匹配,那么它与哪个参数完全匹配
相同的故事.你没有通过任何东西,所以匹配两个参数.
第2步 - 尝试自动装箱或加宽.这应该有助于找出哪一个
如上所述,由于您使用了varargs,因此不允许这样做.
第3步 - 尝试确定哪种类型最小
这是至关重要的区别.这里的类型不具有可比性.这意味着编译器不知道您希望通过参数或最小类型调用哪个方法.因此,它无法找到正确的路线.
第4步 - 拨打电话
如果不知道要调用哪个方法,它就无法继续执行并抛出相应的异常.
在第二个示例中,编译器无法确定要调用的最具体方法.
血淋淋的细节在语言规范中解释,但基本上如果比较两个变量(var-arg)方法,那么如果方法A可以接受传递给方法B的参数,而不是相反,那么方法B最具体.
double> 1 float
漂浮> 1长
长> 1 int
int> 1个字符
int> 1短
短> 1个字节
(其中> 1表示'直接超类型')
在这里,我们可以看到inta比a更具体long,因此fun1(int... b)选择了您的方法.
在第二个例子中,编译器在int和之间进行选择boolean.这些原始类型之间没有子类型关系,因此没有最具体的方法," 方法调用不明确,发生编译时错误. "(15.12.2.5中的最后一行).
当你有intand long(可比较类型)时,默认情况下将使用最小的,这是int(因为你没有传递参数) - 我认为这是因为int 可以扩大到long但long不能(除非你明确地转换它),编译器将选择最低精度类型。
但是当你有boolean和 时int,就无法进行比较,你会得到
The method fun1(int[]) is ambiguous for the type OverloadingVarArgs
Run Code Online (Sandbox Code Playgroud)