You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java同文件类的向下转型代码运行逻辑咨询

Java父类引用指向子类对象的执行逻辑解析

先把你的代码贴出来方便逐点分析:

public class Child extends Base {
 void show() {
 System.out.println("Child");
 }
 void display(){
 System.out.println("Display");
 }
 public static void main(String[] args) {
 Base b=new Child();
 b.show();
 b.display();
 }
}
class Base {
 void show() {
 System.out.println("Base");
 }
}

首先得先点明一个关键问题:这段代码其实编译阶段就会报错,后面我会详细解释原因,再拆解整个逻辑的核心原理。

1. 父类引用指向子类对象的本质

这句Base b = new Child();是Java多态的典型写法,背后的执行逻辑是:

  • JVM会在堆内存中创建一个完整的Child对象,它包含自身定义的show()、display()方法,同时继承了Base类的show()方法(但已经被Child重写覆盖)。
  • 我们把这个Child对象的引用,赋值给了类型为Base的变量b。此时b的编译类型是Base(编译器眼里它就是个Base对象),但实际指向的运行类型是Child(JVM运行时清楚它是个Child对象)。

2. b.show()的执行过程

show()方法在父类Base中定义,子类Child又重写了它,这里触发了Java的**动态绑定(运行时多态)**机制:

  • 编译阶段:编译器检查Base类中是否存在show()方法,发现存在,所以编译通过。
  • 运行阶段:JVM会根据b实际指向的对象类型(Child),去调用Child类中重写的show()方法,所以最终输出Child。

3. b.display()为什么会报错?

这是你这段代码的核心问题:display()方法只在Child类中定义,Base类里完全没有这个方法。
Java的方法调用遵循编译时检查规则:编译器只会根据变量的编译类型(这里是Base)来判断是否能调用某个方法。因为Base类中没有display(),所以编译器直接报错,根本到不了运行阶段。

如果想让display()能被正常调用,有两种解决办法:

  • 在Base类中添加display()方法(哪怕是空实现),让Child类重写它,这样通过b调用时会触发动态绑定,执行Child的display()。
  • 把b强制类型转换为Child类型:((Child) b).display(),这样编译器会识别到这是Child对象,允许调用display()。

核心原理总结

  • 编译看引用类型:编译器只认变量声明的类型,调用的方法必须在该类型中存在,否则编译失败。
  • 运行看实际对象类型:对于编译通过的实例方法,JVM会根据实际对象的类型来调用对应的重写方法,这就是多态的核心。

内容的提问来源于stack exchange,提问作者Abhishek Dubey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:55:58