java方法重写时,子类不得扩大检查型异常范围,仅可缩小或去除;运行时异常可自由添加;若父类未声明检查异常,子类须内部处理或包装为运行时异常。

Java 方法重写时异常抛出规则的核心是:子类不能扩大检查型异常(checked exception)的范围,否则编译直接失败。这不是可选项,而是编译器强制执行的契约约束,目的是保障多态调用的安全性。
只允许缩小或去掉检查型异常
父类方法声明了哪些检查异常,子类重写时只能从中选子集,或者一个都不抛:
- 父类 throws IOException → 子类可写 throws FileNotFoundException(它是 IOException 的子类)
- 父类 throws SQLException → 子类可写 throws SQLTimeoutException(它是 SQLException 的子类)
- 父类 throws IOException, ParseException → 子类可只写 throws IOException,或两者都不写
- 父类没写 throws → 子类也不能新增任何 checked 异常,否则编译报错
运行时异常可以自由添加
RuntimeException 及其子类(如 IllegalArgumentException、NullPointerException、自定义的 XxxException extends RuntimeException)不受限制:
- 父类方法签名是 void doWork(),子类可以 throw new IllegalArgumentException()
- 父类 throws IOException,子类可以同时 throws IOException, IllegalArgumentException
- 这些异常不需要出现在 throws 子句中,也不影响调用方的异常处理逻辑
父类没声明检查异常时,子类要自己消化
当底层调用可能抛出 checked 异常(比如 new FileInputStream() 抛 IOException),但父类方法又没声明 throws 时,子类不能往外甩,必须内部处理:
- 用 try-catch 捕获原始异常
- 包装成运行时异常再抛出,例如 throw new RuntimeException("file init failed", e)
- 或封装为业务意义明确的运行时异常,如 throw new ConfigLoadException("missing config file", e)
- 避免简单吞掉异常(空 catch),丢失上下文
设计层面减少约束冲突
如果多个子类需要抛不同类型的检查异常,说明父类抽象可能不够通用。这时应考虑重构:
- 把父类 throws 提升为更宽泛但合理的类型,比如从 IOException 改为 Exception(需谨慎,会加重调用方负担)
- 改用组合代替继承,让异常处理逻辑解耦到独立服务中
- 引入 Result
或 Optional 等返回值模式,把错误作为数据传递,绕过 throws 机制 - 对校验类逻辑,优先用断言(Objects.requireNonNull)或提前返回,减少异常流
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











