Java中父类引用指向子类对象实现动态方法绑定,核心是编译看父类、运行看子类,需同时满足继承关系、方法重写(非static/final/private)和父类引用调用;static/private/final方法因编译期绑定不参与多态。

Java 中通过父类引用指向子类对象实现动态方法绑定,核心在于继承 + 方法重写 + 运行时多态。这种机制让程序在编译时只知道调用的是父类声明的方法,而实际执行哪个版本,由 JVM 在运行时根据对象的真实类型(即 new 出来的子类类型)决定——这就是动态绑定(也叫后期绑定、运行时绑定)。
前提:必须满足三个条件
只有同时满足以下三点,才能触发动态绑定:
- 有继承关系:子类 extends 父类(或实现接口);
- 有方法重写(Override):子类提供与父类签名完全相同(方法名、参数列表、返回类型协变)、且非 static / final / private 的方法;
- 用父类类型引用指向子类对象:例如 Parent p = new Child();,而不是 Child c = new Child();。
典型代码示例
假设有一个父类 Animal 和两个子类 Dog、Cat:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Cat meows");
}
}
调用方式:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
Animal a1 = new Dog(); Animal a2 = new Cat(); a1.makeSound(); // 输出 "Dog barks" a2.makeSound(); // 输出 "Cat meows"
虽然变量 a1、a2 声明为 Animal 类型,但 JVM 查看它们实际指向的堆中对象(Dog/Cat 实例),从而调用对应子类重写后的方法。
哪些方法不参与动态绑定?
以下情况不会发生动态绑定,而是编译期就确定调用目标(静态绑定):
- static 方法:按引用变量的声明类型决定,不是对象类型;
- final 方法:无法被重写,自然无动态性;
- private 方法:对子类不可见,子类里“同名”方法其实是新定义,不是重写;
- 构造方法:不继承,也不重写,不参与多态。
如何验证确实是运行时绑定?
可以借助 getClass() 和反射辅助观察:
Animal a = new Dog(); System.out.println(a.getClass()); // class Dog System.out.println(a instanceof Dog); // true
这说明引用 a 虽然是 Animal 类型,但它背后的真实对象是 Dog 类型 —— JVM 正是靠这个信息选择方法版本。

















