运行时异常是RuntimeException及其子类,如NullPointerException;受检异常是Exception的子类但非RuntimeException后代,如IOException;编译报错即受检异常,编译通过但运行崩溃多为运行时异常。

看继承关系:RuntimeExeption 及其子类就是运行时异常
最直接、最不会出错的判断方式,就是查源码或文档里的继承链。只要一个异常类是 java.lang.RuntimeException 的后代(比如 NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException),它就是运行时异常;反之,如果它继承自 Exception 但**不是** RuntimeException 的子类(比如 IOException、SQLException、ClassNotFoundException),那就是受检异常。
- IDE 里按住 Ctrl(Windows)或 Cmd(macOS)点击异常类名,一眼就能看到父类
- 别被名字误导:
UnsupportedEncodingException听起来像“不支持”,但它其实是IOException的子类 → 受检异常 -
RuntimeException本身也是Exception的子类,所以“继承自 Exception”这个条件不够,必须排除掉RuntimeException分支
看编译器是否报错:没处理就编译失败的就是受检异常
这是最实用的现场验证方法。把可能抛异常的代码写进方法里,不加 try-catch,也不加 throws,然后尝试编译:
- 如果编译器立刻报错,提示 “unreported exception XXX; must be caught or declared to be thrown”,那
XXX就是受检异常 - 如果代码能顺利编译通过,但运行时可能崩溃(比如打印堆栈后退出),那基本就是运行时异常
- 常见陷阱:有人误以为
new RuntimeException("msg")是“手动抛的”,所以不算——错。它仍是运行时异常,编译器照样不管
FileInputStream fis = new FileInputStream("missing.txt"); // 编译报错:FileNotFoundException is not handled
String s = null; s.length(); // 编译通过,运行时报 NullPointerException看设计意图:外部可变因素 vs 内部逻辑缺陷
区分不只是为了过编译,更是为了决定「要不要捕获」和「怎么修复」:
- 受检异常通常对应**程序无法控制但可预期的外部状况**:文件可能被删、网络可能断、数据库连接可能超时。你得提前想好 fallback 方案(重试?换路径?给用户提示?)
- 运行时异常几乎都指向**代码本身的疏漏**:忘了判空、下标算错、传了非法参数。这时候 catch 住再吞掉,往往只是掩盖问题;更该做的是改
if (obj != null)或加参数校验 - 反例警告:用
try-catch包裹NullPointerException并静默忽略,等于主动放弃调试线索;而对IOException不做任何处理,等于把磁盘故障甩给用户
注意 Error 和 RuntimeException 都属于“非受检”,但地位完全不同
很多人混淆 Error(如 OutOfMemoryError)和运行时异常,以为都能随便 throw。其实它们根本不在一个处理层级:
立即学习“Java免费学习笔记(深入)”;
-
Error是 JVM 层面的灾难性故障,程序基本无法恢复。你不该 catchOutOfMemoryError,更不该在 catch 块里继续分配对象 -
RuntimeException虽然也不强制处理,但它代表的是**可定位、可修复的代码错误**,JVM 留给你的是 debug 机会,不是放弃信号 - 真正容易踩的坑:在日志里捕获了
RuntimeException却没记录堆栈(只打了个e.getMessage()),导致线上问题完全无法复现










