Java方法重写实现多态的关键是JVM运行时根据对象实际类型动态调用,需满足签名一致(方法名、参数列表、协变返回类型、访问权限不更严格)、显式使用@Override注解、通过父类引用指向子类对象调用,且避免在构造器中调用可重写方法。

Java 中继承时方法重写(override)要真正保持行为多态,关键不是“写个同名方法”,而是让 JVM 在运行时根据对象实际类型自动调用对应实现。这需要同时满足语法约束和调用场景设计。
方法签名必须严格一致
子类重写方法必须与父类被重写方法在以下四点完全匹配:
-
方法名相同:大小写、拼写零误差(如
toString()不能写成tostring()); -
参数列表完全一致:个数、类型顺序、擦除后类型均相同(
List<String>和List<Integer>擦除后都是List,但print(List)与print(ArrayList)不构成重写); -
返回类型协变或相同:允许子类返回更具体的子类型(如父类返回
Object,子类可返回String),但不可变宽; -
访问权限不更严格:子类方法不能比父类更私有(
protected父类方法,子类不能声明为private;可升级为public)。
@Override 注解必须显式添加
这不是装饰,而是编译期强制校验开关:
- 防止拼写错误(如
hashcode()误写)导致意外定义新方法而非重写; - 父类方法被删除或改名时,子类立即编译报错,避免静默失效;
- IDE 依赖该注解实现安全重构(如重命名父类方法时自动同步子类)。
调用方式必须符合向上转型前提
多态只在“父类引用指向子类对象”时触发:
立即学习“Java免费学习笔记(深入)”;
- ✅ 正确:
Animal a = new Dog(); a.sound();→ 运行时执行Dog.sound(); - ❌ 无效:
new Animal().sound();或Dog d = new Dog(); d.sound();—— 后者虽调用子类方法,但不体现多态,只是直接调用; - ⚠️ 注意:
static、final、private方法无法重写,子类同名方法属于隐藏或重载,不参与动态绑定。
避免构造器中调用可重写方法
子类字段可能尚未初始化,易引发 NullPointerException 或逻辑错乱:
- 父类构造器中若调用
init(),而该方法被子类重写,此时子类字段仍为默认值(null、0等); - 建议将可重写逻辑延迟到对象构建完成之后,或使用模板方法模式明确控制调用时机。


















