[英]Java overloading with variable length arguments
Why there is no compile error in this code: 为什么此代码中没有编译错误:
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();
}
}
But this code gives compile error! 但是这段代码给出了编译错误!
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();
}
}
I believe there should be compile error in both the case, but this is not so. 我相信在这两种情况下应该存在编译错误,但事实并非如此。
The rules for selecting the correct overloaded method are as follows: 选择正确重载方法的规则如下:
Have a look at that last rule. 看看最后一条规则。 You can not combine widening or boxing with variable length arguments. 您不能将扩展或装箱与可变长度参数组合使用。 That means that the types can not be manipulated in any way and you have to perform the comparison as is. 这意味着不能以任何方式操纵类型,您必须按原样执行比较。 int
and long
can be compared, no problem and the compiler can deduce that int
is the smaller of the two. int
和long
可以比较,没问题,编译器可以推断出int
是两者中较小的一个。 As per the first rule, it will go for the smallest method argument possible, hence it has worked out the correct (and only) route to a method. 根据第一条规则,它将寻找可能的最小方法参数,因此它已经计算出一个方法的正确(和唯一)路由。
However, when you get to boolean
and int
, there exists no comparison method between the two because of Java's strong typing . 但是,当你得到boolean
和int
,由于Java的强类型 ,两者之间不存在比较方法。 With no knowledge of which type is smallest, the compiler has absolutely no clue which method you mean. 由于不知道哪种类型最小,编译器完全不知道你指的是哪种方法。
More Visual Example 更多视觉示例
Let's take it step by step from the perspective of the compiler. 让我们从编译器的角度一步一步地看待它。 First, with int
and long
. 首先,使用int
和long
。
int and long int和long
Step 1 - Checking if the parameters match any arguments and if so, which one it matches exactly 步骤1 - 检查参数是否与任何参数匹配,如果匹配,那么它与哪个参数完全匹配
Well, varargs
means that you can pass 0
to many arguments. 好吧, varargs
意味着你可以传递0
到很多参数。 In this case, you've elected to pass 0
arguments, hence your call matches both the int
type and the long
type. 在这种情况下,您已选择传递0
参数,因此您的调用将匹配int
类型和long
类型。
Step 2 - Attempt to autobox or widen. 第2步 - 尝试自动装箱或加宽。 This should help it work out which one to go for 这应该有助于解决哪一个问题
You're using varargs, so the compiler knows it can't do this, as per the final rule. 您正在使用varargs,因此编译器知道它不能按照最终规则执行此操作。
Step 3 - Attempt to work out which type is smallest 第3步 - 尝试确定哪种类型最小
The compiler is able to compare the type int
with the type long
. 编译器能够将int
类型与long
类型进行比较。 From this, it works out that the int
is the smallest type. 由此可知, int
是最小的类型。
Step 4 - Make the call 第4步 - 拨打电话
With the knowledge that int
is the smallest type, it then passes the value to the method for execution. 知道int
是最小的类型,然后它将值传递给方法执行。
Okay, and now let's do the same thing with boolean
and int
. 好的,现在让我们用boolean
和int
做同样的事情。
boolean and int boolean和int
Step 1 - Checking if the parameters match any arguments and if so, which one it matches exactly 步骤1 - 检查参数是否与任何参数匹配,如果匹配,那么它与哪个参数完全匹配
Same story. 相同的故事。 You've passed nothing so match both arguments. 你没有通过任何东西,所以匹配两个参数。
Step 2 - Attempt to autobox or widen. 第2步 - 尝试自动装箱或加宽。 This should help it work out which one to go for 这应该有助于解决哪一个问题
As above, you're not permitted to do this because you used varargs. 如上所述,由于您使用了varargs,因此不允许这样做。
Step 3 - Attempt to work out which type is smallest 第3步 - 尝试确定哪种类型最小
This is the crucial difference. 这是至关重要的区别。 Here, the types are not comparable. 这里的类型不具有可比性。 This means that the compiler doesn't know which method you want to call by your parameters or by the smallest type. 这意味着编译器不知道您希望通过参数或最小类型调用哪个方法。 Ergo, it has been unable to work out the correct route. 因此,它无法找到正确的路线。
Step 4 - Make the call 第4步 - 拨打电话
Without the knowledge of which method to call, it can not continue execution and throws the appropriate exception. 如果不知道要调用哪个方法,它就无法继续执行并抛出相应的异常。
In your second example, the compiler is unable to determine the most specific method to invoke. 在第二个示例中,编译器无法确定要调用的最具体方法 。
The gory details are explained in the language spec , but essentially if two variable-arity (var-arg) methods are being compared, then if Method A could accept the arguments passed to Method B, but not the other way around, then Method B is most specific. 血淋淋的细节在语言规范中解释,但基本上如果比较两个变量(var-arg)方法,那么如果方法A可以接受传递给方法B的参数,而不是相反,那么方法B最具体。
In your first example, the rules of primitive sub-typing are applied, which are: 在第一个示例中,应用了原始子类型的规则 ,它们是:
double > 1 float double> 1 float
float > 1 long 漂浮> 1长
long > 1 int 长> 1 int
int > 1 char int> 1个字符
int > 1 short int> 1短
short > 1 byte 短> 1个字节
( Where > 1 means 'direct supertype of' ) ( 其中> 1表示'直接超类型' )
Here we can see that an int
is more specific than a long
, so your fun1(int... b)
method is chosen. 在这里我们可以看到int
比long
更具体,因此选择了fun1(int... b)
方法。
In the second example, the compiler is choosing between an int
and boolean
. 在第二个示例中,编译器在int
和boolean
之间进行选择。 There is no sub-type relationship between those primiritve types, therefore there is no most specific method and " the method invocation is ambiguous, and a compile-time error occurs. " (last line in 15.12.2.5). 这些原始类型之间没有子类型关系,因此没有最具体的方法,“ 方法调用不明确,发生编译时错误。 ”(15.12.2.5中的最后一行)。
When you have int
and long
(comparable types), the smallest will be used by default, which is int
(since you're not passing an argument) - I think it's because int
can be widen to long
but long
cannot (unless you explicitly cast it), the compiler will select the lowest precision type. 当你有int
和long
(可比类型)时,默认情况下将使用最小值,这是int
(因为你没有传递参数) - 我认为这是因为int
可以加宽到long
但long
不能(除非你明确 (),编译器将选择最低精度类型。
But when you have boolean
and int
, the comparison cannot be done and you'll get 但是当你有boolean
和int
,无法进行比较而你会得到
The method fun1(int[]) is ambiguous for the type OverloadingVarArgs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.