当重载包含不匹配参数的方法时,JVM将始终使用比参数宽的最小参数的方法。
我已通过以下两个例子证实了上述内容:
扩展:字节扩展为int
class ScjpTest{
static void go(int x){System.out.println("In Int");}
static void go(long x){System.out.println("In long");}
public static void main (String[] args){
byte b = 5;
go(b);
}
}
拳击:int盒装到整数
class ScjpTest{
static void go(Integer x){System.out.println("In Int");}
static void go(Long x){System.out.println("In Long");}
public static void main (String[] args){
int b = 5;
go(b);
}
}
以上两个示例都输出“In Int”,这是正确的。我很困惑,但是当情况涉及var-args时,如下例所示
class ScjpTest{
static void go(int... x){System.out.println("In Int");}
static void go(long... x){System.out.println("In lInt");}
public static void main (String[] args){
byte b = 5; //or even with: int b = 5
go(b);
}
}
以上产生以下错误:
ScjpTest.java:14: reference to go is ambiguous, both method go(int...) in ScjpTest and method go(long...) in ScjpTest match
go(b);
^
1 error
为什么它不应用与前面示例中相同的规则?即将字节扩展为int,因为它是大于字节的最小值?
答案 0 :(得分:5)
var-args语法只是将数组作为参数传递的别名:
foo(int ... arg)
等于foo(int[] arg)
但是数组不是分层的。 String[]
不是Object[]
的子类。完全相同的规则与方法参数相关。因此,当您传递long[]
时,编译器无法区分接受int[]
和byte
的2个重载方法。
答案 1 :(得分:1)
它实际上适用于Java 7:它也为varargs示例返回“In Int”。我想这只是以前版本中缺少的功能。我不知道你正在使用什么Java版本,但也许它也适用于Java 6。
然而,我必须说,即使你的第一个例子有效,我也感到惊讶(没有varargs)。我不知道原始的扩大转换。 顺便说一句,如果您改为使用Byte,Integer和Long,那么您的第一个和最后一个示例将失败,因为这些类型之间没有层次结构(除了它们都是Number的子类)。
答案 2 :(得分:1)
正如AlexR指出的那样,var-args就像一个数组。基元的数组(例如byte[] short[] int[] long[] float[] double[]
)似乎在内部编译到同一个类。这就是为什么你的重载方法是模糊的。但是下面的代码是完全有效的:
static void go(int... x){System.out.println("In Int");}
static void go(Long... x){System.out.println("In lInt");}
这成功编译(因为int[]
和Long[]
是不同的类型),并生成输出In Int
。
如果您正在为SCJP做准备,我强烈建议您阅读本书SCJP Sun Certified Programmer for Java 6 Exam 310-065。本书中的重载部分涵盖了混合装箱和var-args的所有技巧。