学了很长时间的java了,现在重新来讨论一下这个问题,因为这个问题还是很能够糊弄人的。
先来看一段代码
public class Test{
public static void say(Object arg){
System.out.println("object");
}
public static void say(int arg){
System.out.println("int");
}
public static void say(char arg){
System.out.println("char");
}
public static void say(long arg){
System.out.println("long");
}
public static void say(char... arg){
System.out.println("char...");
}
public static void say(Character arg){
System.out.println("Character");
}
public static void say(Serializable arg){
System.out.println("Serializable");
}
public static void main(String[] args){
say('a');
}
}
输出结果为
char
这也很好解释,优先肯定匹配类型相同的
如果我们注释掉
public static void say(char arg){
System.out.println("char");
}
输出结果为
int
这是因为此时发生了一次类型转换,'a'除了可以代表一个字符串,还可以代表数字97,因此参数类型为int的重载也是合适的,
继续注释say(int arg)
输出结果为 long
这个时候发生了两次自动类型转换,'a'转型为整数97之后进一步转型为97L,匹配的参数类型为long的重载,
代码中没有写float,double的重载,实际上自动类型转换还能继续发生多次,按照char->int->long->float->double的顺序进行匹配,但不会匹配到byte和short类型的重载,因为char转byte和short的转型是不安全的。
我们继续注释say(long arg),
输出结果为Character,
这次发生了一次自动装箱,继续注释掉say(Character arg),
输出结果为Seriablizable,
这事因为java.long.Seriablizable是java.long.Character类实现的接口,当自动装箱之后发现找不到装箱类,但是找到装箱类实现的接口类型,所以紧接着又发生了一次自动转型。
继续注释say(Seriablizable arg)之后,
结果就变成了Object,
这是因为char装箱成Character之后转型父型了,因为Object是所有类的父类,
继续注释say(Object arg)之后,
结果为Char...
可见数组参数重载的优先级最低。
上面的过程演示了便宜期间选择静态分配目标的过程,这个过程也是java语言实现重载的本质。