标题太大,在这里写一部分,在 JVM 中,方法的调用被广泛称为分派,运行期根据实际类型确定方法执行版本的分派过程称为动态分派,如重写方法的调用。
动态分派的理解:根据对象的实际类型,来确认调用的方法版本,子类有重写方法,则调用子类的重写方法,否则去父类找对应的方法,这就是 invokevirtual 指令的执行逻辑,这是 java 里面对于方法重写的本质。
以下代码中的 Father gay = new Son(); 中,Father 称为变量的静态类型,Son 称为变量的实际类型。
这里贴出一段代码,思考 main 方法的输出是什么,在看结果
public class FieldHasNoPolymorphic {
static class Father{
public int money = 1;
public Father(){
money = 2;
showMeTheMoney();
}
public void showMeTheMoney(){
System.out.println("I am Father, i have $" + money);
}
}
static class Son extends Father{
public int money = 3;
public Son(){
money = 4;
showMeTheMoney();
}
public void showMeTheMoney(){
System.out.println("I am Son, i have $" + money);
}
}
public static void main(String[] args){
Father gay = new Son();
System.out.println("This gay has $" + gay.money);
}
}执行结果如下:

对执行结果的解释:
第一行:调用 Son 构造的时候,会先隐式调用父类构造,父类构造执行调用 showMeTheMoney 方法的时候,根据动态分派原理调用了 Son 的 重写方法,方法中对 money 的调用是 Son 的 money,值为0
第二行:相信大家都能理解
第三行:通过静态类型访问到了父类的 money,输出了2
以上内容来自《深入理解Java虚拟机》:JVM高级特性与最佳实践(第三版) 周志明著,8.3.2 节 分派
思考:子类的初始化动作 int money 在 Father() 之前执行(没有疑问,类加载器的初始化阶段),但是子类的 public in money = 3; 竟然在 Father() 之后执行,有知道的欢迎评论区讨论。
转载请在明显位置附上原文链接。
版权声明:本文为wf13265原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。