Java方法重写必须满足四规则:访问权限不更严格、返回类型兼容(协变)、方法签名完全一致、抛出异常不更宽泛;@Override注解是强制性契约,用于编译期校验重写正确性。

Java 中方法重写(Override)不是简单地“名字一样就行”,必须满足四个核心规则,否则编译失败或行为异常;@Override 注解不是可选修饰,而是强制性的开发实践——它让编译器帮你检查是否真的重写了父类方法,避免拼写错误、参数不匹配等低级但致命的问题。
规则一:访问权限不能更严格
子类重写方法的访问修饰符,必须等于或比父类方法更宽松。比如父类是 protected,子类可以是 protected 或 public,但不能是 private 或默认(包私有)。
- ✅ 合法:
protected void show()→public void show() - ❌ 编译报错:
public void show()→private void show() - ⚠️ 注意:default(无修饰符)权限介于 protected 和 private 之间,不可用于缩小范围
规则二:返回类型必须兼容(协变返回类型)
Java 5 开始支持协变返回类型:子类方法的返回类型可以是父类方法返回类型的子类型(包括相同类型)。基本类型和 void 不适用协变,必须完全一致。
- ✅ 合法:
Animal getPet()→Dog getPet()(Dog 是 Animal 子类) - ✅ 合法:
void run()→void run()(void 必须严格相同) - ❌ 编译报错:
String getName()→Object getName()(扩大返回类型不被允许)
规则三:方法签名必须完全一致
方法名、参数列表(类型、个数、顺序)必须与父类方法一模一样。仅改变返回类型、异常声明或访问修饰符不算重写;改变参数类型(如 int → Integer)属于重载,不是重写。
立即学习“Java免费学习笔记(深入)”;
- ✅ 重写:
public void eat(String food)→public void eat(String food) - ❌ 重载(非重写):
public void eat(String food)→public void eat(String food, int times) - ❌ 编译失败:
public void save(File f)→public void save(Path p)(参数类型不同,签名不匹配)
规则四:抛出异常只能减少或不变
子类重写方法不能抛出比父类方法更宽泛的检查型异常(checked exception),但可以抛出更具体的检查型异常,或不抛出任何异常;运行时异常(RuntimeException 及其子类)不受限制。
- ✅ 合法:
void read() throws IOException→void read() throws FileNotFoundException(FileNotFoundException ⊆ IOException) - ✅ 合法:
void parse() throws Exception→void parse()(不抛异常也允许) - ❌ 编译报错:
void connect()→void connect() throws SQLException(无声明 → 新增检查型异常,不允许)
@Override 注解:不是装饰,是契约
@Override 是编译期注解,唯一作用是告诉编译器:“我明确打算重写父类/接口中的某个方法”。一旦加了它,编译器就会严格校验上述四条规则是否满足。若不满足,直接报错,而不是静默忽略或变成重载。
- ? 好处:避免手误(如
draw()写成drow())、防止父类方法被删后子类方法“失效”而不自知 - ⚠️ 注意:实现接口抽象方法时也应加 @Override(Java 6+ 支持),这同样能防止接口升级后方法签名变更导致的遗漏
- ? 不要省略:哪怕你“确定”自己写对了——机器比人更可靠


















