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

Java中多态成员方法的动态绑定(也叫运行时绑定或晚期绑定)是指:当通过父类引用调用一个被子类重写的方法时,JVM在运行时根据实际对象的类型(而非引用变量的声明类型)来决定调用哪个版本的方法。这个机制是实现多态的核心。
动态绑定发生的前提条件
只有满足以下三个条件,方法调用才会触发动态绑定:
- 方法必须是非private、非static、非final的实例方法(即普通可被重写的方法)
- 子类中存在对父类该方法的重写(override),而不是重载(overload)
- 调用是通过父类类型的引用变量,但指向的是子类创建的对象(即发生了向上转型)
JVM如何执行动态绑定
JVM在类加载阶段为每个类生成一个“虚方法表”(Virtual Method Table,简称vtable)。表中按声明顺序存放该类所有可被动态绑定的方法入口地址。子类vtable会继承父类vtable,并将被重写的方法条目替换为子类对应方法的实际地址。
当执行类似 parentRef.method() 的调用时:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- JVM先根据
parentRef的实际运行时类型(比如是Child类实例),定位到该类型的vtable - 再根据方法签名(名称+参数类型)查vtable,找到对应方法的具体入口地址
- 最后跳转执行该地址处的字节码
哪些方法不参与动态绑定
以下情况不会触发动态绑定,而是编译期就确定调用目标(静态绑定):
- static 方法:基于引用类型(声明类型)决定调用哪个类的static方法
- private 方法:隐式 final,仅在本类可见,子类中的同名方法是独立方法,不是重写
- 构造方法:不能被重写,只属于当前正在初始化的类
- final 方法:明确禁止重写,编译器直接内联或固定绑定
一个典型例子说明执行过程
假设定义了:
class Animal { void sound() { System.out.println("Animal sound"); } }
class Dog extends Animal { void sound() { System.out.println("Woof!"); } }
Animal a = new Dog(); a.sound(); // 输出 "Woof!"
虽然变量 a 声明为 Animal 类型,但运行时它指向 Dog 实例。JVM查 Dog 类的vtable,发现 sound() 条目指向 Dog.sound() 的字节码,于是执行子类版本。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










