父类引用指向子类对象是java多态的运行基础,编译看父类声明、运行看实际子类类型,实现动态绑定与“一个接口、多种实现”。

父类引用指向子类对象,本质是 Java 多态的运行基础,不是类型转换操作,而是编译期与运行期分工协作的结果。它让同一段调用代码,根据实际对象类型执行不同逻辑,实现“一个接口、多种实现”。
编译看左边,运行看右边
声明时用父类类型(如 Animal a),编译器只检查 Animal 中是否定义了要调用的方法;但真正执行时,JVM 会查看 a 实际指向的是哪个子类实例(比如 Dog 或 Cat),再决定调用哪个版本的 eat()。
- 编译阶段:只允许调用父类声明过的方法,哪怕子类重写了,也得有父类方法签名作“入口”
- 运行阶段:JVM 通过 invokevirtual 指令动态查找子类中重写的方法并执行
- 字段访问不参与多态:无论背后是 Dog 还是 Cat,a.name 永远取 Animal 类里定义的字段值
向上转型是自动且安全的
写 Animal a = new Dog(); 不需要强制类型转换,因为子类天然具备父类全部能力(is-a 关系)。这种隐式转型让代码更简洁,也避免了类型错误。
- 父类引用可以统一接收任意子类对象,例如传入 feed(Animal a) 方法
- 新增子类(如 Tiger)时,原有方法无需修改,符合开闭原则
- 不能调用子类特有方法(如 Dog.fly()),否则编译直接报错
动态绑定依赖方法重写,不是重载
只有满足重写条件的方法才能触发多态行为:子类中存在与父类同名、同参数列表、同返回类型、非 private / final / static 的方法。
- 重载(overload)发生在编译期,靠参数区分,和多态无关
- 重写(override)是运行时多态的前提,没有重写就没有“不同实现”
- @Override 注解不是必需的,但能帮助编译器校验是否真正在重写父类方法
向下转型需谨慎,必须配合 instanceof
如果确实需要调用子类特有功能(如 Dog.bark()),就得把父类引用转回子类类型。但这不是自动的,也不能保证成功。
- 强制写 (Dog) a 可能抛出 ClassCastException
- 安全做法是先用 if (a instanceof Dog) 判断类型
- 向下转型破坏了多态的抽象性,应尽量避免,优先通过设计扩展父类接口来解决










