public class Yikes {
public static void go(Long n) {
System.out.print("Long ");
}
public static void go(Short n) {
System.out.print("Short ");
}
public static void go(int n) {
System.out.print("int ");
}
public static void main(String[] args) {
short y = 6;
long z = 7;
go(y);
go(z);
}
}
这个程序给出了输出
int Long
我以为输出是
short Long
这是什么原因?
JLS中的重载解析部分解释了原因:
- 第一阶段(§15.12.2.2)执行重载解析,不允许装箱或拆箱转换,也不允许使用变量性方法调用。如果在此阶段没有找到适用的方法,则继续进行第二阶段的处理。
这保证了在Java SE 5.0之前在Java编程语言中有效的任何调用不会因为引入变量性方法、隐式装箱和/或拆箱而被认为是不明确的。然而,可变密度方法的声明(§8.4.1)可以改变为给定方法方法调用表达式选择的方法,因为可变密度方法在第一阶段被视为固定密度方法。例如,在一个已经声明了
m(Object)
的类中声明m(Object...)
,会导致m(Object)
不再被某些调用表达式选择(例如m(null))
,因为m(Object[])
更具体)。
- 第二阶段(§15.12.2.3)在允许装箱和拆箱的情况下执行重载解析,但仍然禁止使用变量性方法调用。如果在此阶段没有找到适用的方法,则继续进行第三阶段的处理。
在第一阶段,编译器在其解析中不包括go(Short n)
方法。相反,它认为go(int n)
是一个适用的方法。这个方法是适用的,因为short
被扩展为int
。
编译器倾向于将short
对象转换为int
对象,而不是将其打包为Short
对象。
试试这个:
不是public static void go(Short n) {
System.out.print("Short ");
}
试
public static void go(short n) {
System.out.print("Short ");
}