方法覆盖是Java多态实现的核心机制,需满足继承关系、方法签名一致、返回类型协变、访问权限不缩紧、异常范围不扩大;@Override提供编译期校验;运行时依据实际对象类型而非引用类型绑定方法;private/static/final方法不可覆盖。

方法覆盖是 Java 多态性落地的核心机制,它让“同一调用,不同行为”成为可能。多态不是靠语法糖自动生效的,而是依赖覆盖规则 + 运行时绑定共同保障的。
覆盖必须满足严格条件,否则多态失效
只有当子类方法真正构成合法覆盖时,JVM 才会在运行时选择子类版本。不满足任一条件,就只是重载或独立方法,无法触发多态:
- 必须有继承关系(子类 extends 父类)
- 方法名、参数列表(个数、类型、顺序)必须完全一致
- 返回类型相同,或为父类返回类型的子类(协变返回,如父类返回
Animal,子类可返回Dog) - 访问权限不能比父类更严格(
public可覆盖protected,但反过来不行) - 抛出的异常不能比父类更多(可以更少,或不抛)
@Override 注解是安全网,不是装饰品
加上 @Override 不仅是代码规范,更是编译期校验工具:
- 如果方法签名写错(比如参数类型写成
int而非Integer),编译器立刻报错 - 如果父类方法被删了或改名了,带注解的方法会高亮提醒你同步调整
- 避免手误导致“看似覆盖、实则新增”,从而让多态逻辑静默失效
多态执行依赖运行时类型,而非引用类型
关键在对象实际创建的是哪个类——不是看变量声明类型,而是看 new 后面的类:
立即学习“Java免费学习笔记(深入)”;
-
Animal a = new Dog();→ 调用a.move()执行的是Dog.move() -
Animal a = new Cat();→ 同样调用a.move(),却执行Cat.move() - 即使把
Dog对象赋给Animal类型变量,JVM 仍通过对象头中的类元信息定位到Dog类的方法表
父类方法不能是 private / static / final
这些修饰符会切断覆盖链,直接阻断多态路径:
-
private方法不可见、不可继承,子类里同名方法只是新方法,与多态无关 -
static方法属于类,不参与实例方法的动态绑定,调用取决于引用类型(Animal.say()永远走Animal的静态方法) -
final方法禁止覆盖,强制使用父类实现,失去子类定制能力


















