Exception是程序可预见、可恢复的异常,应捕获处理;Error是JVM或系统级严重故障,不可恢复,不应捕获。二者均为Throwable直接子类,但Exception属“人祸”,Error属“天灾”。

区分 Exception 和 Error 的关键,不在于它们“长什么样”,而在于它们代表的问题性质、可处理性以及 JVM 的设计意图。二者同为 Throwable 的直接子类,但定位截然不同。
核心定位:人祸 vs 天灾
这是最直白也最准确的区分逻辑:
- Exception 是“人祸”——程序本身能预见、能干预、该由开发者负责的异常情况。比如文件找不到、网络超时、空指针调用、数组越界。它提示:代码逻辑或外部依赖出了问题,你得管。
-
Error 是“天灾”——JVM 自身崩溃、资源彻底耗尽、类加载失败等底层灾难。比如
OutOfMemoryError、StackOverflowError、NoClassDefFoundError。它提示:运行环境已不可靠,程序大概率无法继续,你不该、也不能指望靠try-catch挽救。
能否捕获?不是能不能,而是该不该
语法上,catch (Throwable t) 确实能捕获两者,但实际开发中:
- 捕获 Exception 是常规操作。检查型异常(如
IOException)必须处理;运行时异常(如NullPointerException)虽不强制,但常需针对性修复或兜底。 - 捕获 Error 属于反模式。即使写了
catch (Error e),也极少有意义——JVM 状态可能已损坏,继续执行风险极高。日志记录可以,恢复业务逻辑基本不可行。
编译器是否插手?看“检查性”而非继承关系
注意:编译器只对 部分 Exception 强制检查,和 Error 完全无关:
-
编译时异常(Checked Exception):所有非
RuntimeException的Exception子类,如FileNotFoundException。编译器会报错,逼你写try-catch或加throws。 -
运行时异常(Unchecked Exception):
RuntimeException及其子类,如ArrayIndexOutOfBoundsException。编译器放行,但运行时炸给你看。 -
Error 全部是 unchecked:编译器从不检查
Error,无论你写不写catch,它都只在运行时爆发。
怎么一眼识别?看类名和常见场景
实战中快速判断:
- 见到
OutOfMemoryError、VirtualMachineError、NoClassDefFoundError、LinkageError—— 这是 Error,查 JVM 配置、内存、类路径。 - 见到
IOException、SQLException、ClassNotFoundException—— 这是 Checked Exception,必须显式处理。 - 见到
NullPointerException、IllegalArgumentException、ArithmeticException—— 这是 Unchecked Exception(即RuntimeException),重点在代码逻辑审查和防御性编程。

















