原力计划( 二 )


System.out.println(\"hello char\");
}
private static void sayHello(Object arg){
System.out.println(\"hello Object\");
}
private static void sayHello(int arg){
System.out.println(\"hello int\");
}
private static void sayHello(long arg){
System.out.println(\"hello long\");
}
// 测试代码
public static void main(String[] args) {
sayHello('a');
}
}
// 运行结果
hello char
因为‘a’除了可代表字符串,还可代表数字97 。因此当没有最合适的sayHello(char arg)方式进行重载时,会选择第二合适(第二优先级)的方法重载,即
hello int
因为‘a’除了可代表字符串,还可代表数字97 。因此当没有最合适的sayHello(char arg)方式进行重载时 , 会选择第二合适(第二优先级)的方法重载,即sayHello(int arg)
总结:当没有最合适的方法进行重载时,会选优先级第二高的的方法进行重载 , 如此类推 。
优先级顺序为:char>int>long>float>double>Character>Serializable>Object>...
其中...为变长参数,将其视为一个数组元素 。变长参数的重载优先级最低 。
因为 char 转型到 byte 或 short 的过程是不安全的,所以不会选择参数类型为byte 或 short的方法进行重载,故优先级列表里也没有 。
特别注意,上面讲解的主要是基本数据类型的优先级匹配问题,若是引用类型,则根据继承关系进行优先级匹配,注意只跟其编译时类型(即静态类型)相关 。
动态分派
定义:根据变量的动态类型,进行方法分派的行为,即根据变量的动态类型确定执行哪个方法 。
应用场景:方法重写(Override)
实例说明
// 定义类
class Human {
public void sayHello{
System.out.println(\"Human say hello\");
}
}
// 继承自 抽象类Human 并 重写sayHello
class Man extends Human {
@Override
protected void sayHello {
System.out.println(\"man say hello\");
}
}
class Woman extends Human {
@Override
protected void sayHello {
System.out.println(\"woman say hello\");
}
}
// 测试代码
public static void main(String[] args) {
// 情况1
Human man = new man;
man.sayHello;
// 情况2
man = new Woman;
man.sayHello;
}
}
// 运行结果
man say hello
woman say hello
// 原因解析
// 1. 方法重写(Override) = 动态分派 = 根据 变量的动态类型 确定执行(重写)哪个方法
// 2. 对于情况1:根据变量(Man)的动态类型(man)确定调用man中的重写方法sayHello
// 3. 对于情况2:根据变量(Man)的动态类型(woman)确定调用woman中的重写方法sayHello

特别注意,对于代码中:Human man = new Man;
man = new Woman;
man.sayHello;
// man称为执行sayHello方法的所有者,即接受者 。
invokevirtual指令执行的第一步 = 确定接受者的实际类型 。
invokevirtual指令执行的第二步 = 将 常量池中 类方法符号引用 解析到不同的直接引用上 。第二步即方法重写(Override)的本质 。
二者区别
声明:本文为CSDN博主「Carson_Ho」的原创文章 。

相关经验推荐