Java多态依赖运行时动态绑定,核心是根据对象实际类型调用重写后的方法,需同时满足继承/实现关系、子类重写非static/private/final方法、父类或接口类型引用指向子类实例三个条件。
多态靠动态绑定,不是编译时决定的
Java 多态的核心是「运行时根据对象实际类型调用方法」,而不是看变量声明的类型。比如 Animal a = new Dog(),编译器只检查 Animal 类里有没有 makeSound();真正执行时,JVM 查的是 new Dog() 这个对象的实际类型,然后去 Dog 的方法表里找重写后的实现。
- 静态方法、
private方法、final方法不参与动态绑定——它们在编译期就绑定了,调用时只看引用的编译时类型 - 构造方法不能被重写,所以也不构成多态
- 接口实现和类继承效果一致:只要
Shape s = new Circle()且Circle实现了draw(),就触发动态绑定
必须同时满足三个条件,缺一不可
光写个 @Override 不等于有多态;光有继承也不行。真正生效要三者齐备:
- 存在继承或实现关系(
extends或implements) - 子类重写了父类/接口中的非静态、非私有、非 final 方法
- 使用父类/接口类型引用指向子类实例(即向上转型:
Animal a = new Cat())
常见错误:写成 Cat c = new Cat(); c.makeSound(); ——这没用到父类引用,只是普通调用,不体现多态;或者子类没加 @Override 却以为重写了,结果调用的还是父类方法。
方法表(vtable)是 JVM 实现动态绑定的关键结构
JVM 为每个类维护一张方法表,表中按签名顺序存放可被动态调用的方法地址。子类加载时,会复制父类方法表,再把重写的方法替换成自己的入口地址。调用时,JVM 直接查这张表,跳转到对应实现。
立即学习“Java免费学习笔记(深入)”;