Java多态通过动态绑定实现,即运行时根据对象实际类型而非引用类型决定方法调用目标;需满足继承、重写非static/final/private方法、父类引用指向子类对象三个前提;JVM通过虚方法表(vtable)在运行时定位具体实现。

Java 中的多态通过动态绑定(也叫运行时绑定、晚期绑定)实现行为切换,核心在于:**方法调用的实际执行目标,在运行时根据对象的实际类型(而非引用类型)决定,而不是编译时就固定下来。**
动态绑定发生的前提条件
要触发动态绑定,必须同时满足三个条件:
- 存在继承关系(子类 extends 父类 或 实现接口)
- 子类重写(override)了父类的非静态、非 final、非 private 的实例方法
- 使用父类(或接口)类型的引用变量,指向子类创建的对象(即“向上转型”)
方法调用如何在运行时定位到具体实现
JVM 在类加载阶段为每个类构建虚方法表(vtable),表中按声明顺序存放该类所有可被动态绑定的方法入口地址。当执行类似 obj.method() 的调用时:
- 编译期只检查 obj 的声明类型是否含 method(),通过则生成 invokevirtual 指令
- 运行期 JVM 查看 obj 实际指向的对象所属类的 vtable,直接跳转到该类中 method() 对应的字节码地址
- 若子类未重写,就沿继承链向上查找,直到找到首个实现(可能在父类)
哪些方法不参与动态绑定
以下情况不会触发动态绑定,而是由编译期决定调用目标(即静态绑定):
立即学习“Java免费学习笔记(深入)”;
- static 方法:依赖引用类型,不是对象类型。例如 Parent p = new Child(); p.staticMethod() 调用的是 Parent.staticMethod
- private 方法:隐式 final,仅在本类可见,无法被重写,编译器直接内联或绑定到当前类
- final 实例方法:禁止重写,JVM 可优化为静态绑定
- 构造方法:不支持重写,也不属于多态范畴
一个典型例子说明行为切换过程
假设定义:
class Animal { void speak() { System.out.println("Animal sound"); } }
class Dog extends Animal { void speak() { System.out.println("Woof!"); } }
class Cat extends Animal { void speak() { System.out.println("Meow!"); } }
执行以下代码:
- Animal a = new Dog(); a.speak(); → 输出 Woof!
- a = new Cat(); a.speak(); → 输出 Meow!
- 同一变量 a,仅因实际对象变化,speak() 行为就自动切换——这就是动态绑定驱动的多态表现


















