关键在继承关系与编译器态度:受检异常继承Exception但非RuntimeException子类(如IOException),编译强制处理;非受检异常包括RuntimeException子类(如NullPointerException)和Error子类(如OutOfMemoryError),编译不强制处理。

区分 Java 中的受检异常和非受检异常,关键不在名字,而在继承关系和编译器态度。
看继承关系:这是最根本的判断依据
所有异常都继承自 Throwable,但分叉点在 Exception 和 RuntimeException:
- 受检异常:直接继承自 Exception,且不是 RuntimeException 的子类。例如
IOException、SQLException、ClassNotFoundException - 非受检异常:包括两类
✓ 继承自 RuntimeException(如NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException)
✓ 继承自 Error(如OutOfMemoryError、StackOverflowError)
注意:自定义异常时,继承 Exception 就是受检的,继承 RuntimeException 就是非受检的——跟类名里有没有 “Exception” 字样完全无关。
看编译器是否强制你处理
这是最直观的验证方式:
立即学习“Java免费学习笔记(深入)”;
- 受检异常:不处理就编译失败。必须用
try-catch捕获,或在方法签名中用throws声明 - 非受检异常:编译器完全不管。你可以捕获,也可以放任它运行时炸开;即使写了
catch (RuntimeException e),编译也通过
比如调用 FileReader 构造方法,IDE 会立刻标红提醒你处理 FileNotFoundException——这就是典型的受检异常信号。
看设计意图:为什么这么分
分类背后是责任划分逻辑:
- 受检异常代表外部可预期、调用方有能力恢复的问题,比如文件不存在、网络超时、数据库连接失败。系统“逼”你正视它,因为用户可能换路径、重试、提示操作
- 非受检异常代表程序自身缺陷或不可恢复的系统故障。比如空指针、数组越界,本质是 bug,该修代码而不是写一堆
catch掩盖;Error更是 JVM 层面问题,通常无法在应用层修复
所以面试中讲区别,重点不是背“编译时/运行时”,而是说清“谁该负责”和“值不值得兜底”。


















