关键看编译器是否强制处理:受检异常继承exception但不继承runtimeexception(如ioexception),必须try-catch或throws;非受检异常继承runtimeexception或error(如nullpointerexception、outofmemoryerror),编译时不检查。

区分受检异常和非受检异常,关键看编译器是否强制你处理它——不是看名字,而是看继承关系和设计意图。
看继承关系:这是最硬的判断标准
受检异常继承自 Exception,但**不继承 RuntimeException**;非受检异常要么继承 RuntimeException,要么继承 Error。
- IOException、SQLException、ClassNotFoundException → 受检异常(编译不过,必须处理)
- NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException → 非受检异常(编译放行,运行才爆)
- OutOfMemoryError、StackOverflowError → 非受检异常(属于 Error,一般不捕获)
看处理方式:编译器会“盯住”你
受检异常出现在方法中,你只有两种选择,缺一不可:
- 用 try-catch 捕获并处理(比如重试、记录日志、友好提示)
- 在方法签名加 throws 声明,把责任交给上层调用者
非受检异常完全自由:你可以 catch,也可以不管;可以 throws 声明,也可以不写——编译器不拦着。
看使用场景:问两个问题就能选对
定义一个异常该受检还是非受检,本质是权衡责任和恢复能力:
- 调用方能否、是否应该响应这个错误?比如文件读取失败,可以换路径或提示用户 → 适合受检
- 这个错误是不是本该在开发阶段就发现?比如传 null 导致空指针 → 属于 bug,修复代码比 try-catch 更重要 → 适合非受检
现代框架(如 Spring)常把底层的 SQLException 包装成非受检的 DataAccessException,正是为了减少模板代码、避免异常污染 API。
自定义异常时怎么选?直接决定继承谁
想让自己的异常被编译器“盯住”,就继承 Exception;想让它像 NullPointerException 一样自由,就继承 RuntimeException:
- class BusinessValidationException extends Exception → 受检,调用方必须处理
- class InvalidOrderException extends RuntimeException → 非受检,按需捕获即可
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











