子类重写父类方法时异常声明须遵循“宽进严出”原则:可减少或细化检查异常,不可增加更宽泛的检查异常;运行时异常不受限;父类未声明检查异常时子类不得新增;此举保障多态调用安全与里氏替换原则。

子类重写父类方法时,异常声明必须遵循“宽进严出”原则:子类方法可以抛出更少或更具体的异常,但不能抛出额外的、更宽泛的检查异常(checked exception)。
父类方法声明了检查异常,子类重写时只能缩小或保持不变
如果父类方法声明 throws IOException,子类重写该方法时:
- 可以不声明任何异常(即不写 throws)
- 可以只声明 IOException 的子类,比如 FileNotFoundException
- 不能声明 Exception、SQLException 等与 IOException 无关或更宽泛的检查异常
- 运行时异常(RuntimeException 及其子类)不受限制,子类可自由添加或删除 throws 声明
父类方法没声明检查异常,子类重写时不能新增检查异常
若父类方法签名是 void doWork()(无 throws),子类重写时:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 不能写成 void doWork() throws IOException
- 可以抛出任意运行时异常,例如 IllegalArgumentException、NullPointerException
- 这是为了保证多态调用安全:父类引用指向子类对象时,调用方只需按父类契约处理异常
编译器强制校验,违反规则直接报错
Java 编译器会在重写时静态检查 throws 子句。例如:
class Parent {
void method() throws IOException {}
}
class Child extends Parent {
// ❌ 编译错误:Cannot override method() throws SQLException
void method() throws SQLException {}
}
这种设计保障了里氏替换原则(Liskov Substitution Principle)——子类对象能安全替代父类对象,而不会让原有异常处理逻辑失效。
实际建议:优先用运行时异常,减少 throws 约束
为提升 API 灵活性和降低继承干扰,可考虑:
- 将业务上不可恢复的错误建模为 RuntimeException 子类(如自定义 ValidationException)
- 对真正需要调用方显式处理的场景,才使用 checked exception
- 若父类用了 checked exception,子类想简化调用,可在内部捕获并转为运行时异常(需谨慎权衡语义)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










