Java虚拟机通过静态分派(编译期依据声明类型决定重载方法)和动态分派(运行期依据实际类型决定重写方法)共同实现多态;前者解决“调哪个重载”,后者解决“走哪个重写”。

Java虚拟机通过静态分派和动态分派两个阶段决定调用哪个方法。静态分派在编译期完成,依据的是变量的**声明类型**;动态分派在运行期完成,依据的是对象的**实际类型**。这是理解重载(overload)与重写(override)底层机制的关键。
静态分派:靠声明类型选方法
静态分派发生在编译阶段,JVM不参与,由javac根据方法调用处的**引用类型(即声明类型)** 和**参数的编译期类型**来确定调用哪个重载版本。它只看代码写成什么样,不关心运行时对象真实是什么。
- 典型场景是方法重载(overload)
- 例如:Object obj = new String("hello");,虽然obj实际是String,但静态类型是Object,调用print(Object)而非print(String)
- 编译器会生成invokestatic或invokevirtual指令,但目标方法签名已在class文件中固定
动态分派:靠实际类型找实现
动态分派发生在运行期,JVM根据调用者的**实际类型(即new出来的类型)**,在该类型的方法表(vtable)中查找最终要执行的方法版本。它是实现多态的核心机制。
- 典型场景是实例方法重写(override)
- 例如:Animal a = new Dog(); a.sound();,虽然a声明为Animal,但JVM查Dog类的方法表,执行Dog的sound()
- 触发条件:必须是非私有、非静态、非final的实例方法调用
- 底层依赖invokevirtual指令,它会查接收者对象的实际类、逐级向上找重写版本
区分关键点:看什么类型?什么时候定?
一句话记住区别:静态分派看“左边”,动态分派看“右边”——声明类型在等号左边,实际类型在等号右边(new后面)。
立即学习“Java免费学习笔记(深入)”;
- 静态分派:由编译器决定,不可变,影响重载解析
- 动态分派:由JVM在运行时决定,可变,影响重写执行
- 字段访问、static方法、final方法、private方法不参与动态分派
基本上就这些。静态分派解决“该调哪个重载”,动态分派解决“该走哪个重写”。两者配合,才让Java的多态既灵活又可控。










