error是jvm系统级故障,不可恢复,不应捕获;exception是程序逻辑或环境异常,可干预处理,应按设计意图区分检查型与运行时异常进行应对。

区分 Error 和 Exception 的本质,关键不在“谁更吓人”,而在于它们代表的问题源头、恢复可能性以及设计意图。
问题根源不同:JVM系统级故障 vs 程序逻辑或环境波动
Error 描述的是 JVM 自身运行崩溃或底层资源彻底失效的情形,比如内存耗尽(OutOfMemoryError)、调用栈溢出(StackOverflowError)、类加载器找不到核心类(NoClassDefFoundError)。这些问题和你的业务代码逻辑无关,而是运行环境已失去支撑能力。
Exception 则源于程序与外部交互或内部逻辑执行中可预见的异常路径,比如文件被删除(FileNotFoundException)、网络超时(SocketTimeoutException)、数组越界(ArrayIndexOutOfBoundsException)或空指针访问(NullPointerException)。它反映的是“程序在当前条件下走不通”,但环境本身仍稳定可用。
是否可恢复:不可恢复性 vs 可干预性
Error 通常不具备程序内恢复条件。例如,JVM 已经触发 OOM,堆空间全满,此时任何 try-catch 都无法凭空腾出内存;栈已爆满,再递归一次就直接终止线程。这类错误发生后,JVM 往往进入不稳定状态,强行捕获并继续执行可能引发数据错乱或二次崩溃。
Exception 具备明确的干预空间:
- 检查型异常(如
IOException)强制你思考“如果读不到文件怎么办”,可以重试、换路径、提示用户重新选择; - 运行时异常(如
IllegalArgumentException)提示你校验入参,提前拦截非法输入; - 即使抛出了
NullPointerException,也能通过日志定位空值来源,修复逻辑或增加判空保护。
语言设计立场:不该捕获 vs 应该处理
Java 明确将 Error 定义为“不期望应用程序捕获”的类型。编译器不强制处理,IDE 也不建议加 try-catch —— 因为这不是你代码该兜底的层级。
Exception 是 Java 异常处理机制真正服务的对象:
- Checked Exception(编译期异常)必须显式声明或捕获,倒逼开发者正视外部依赖风险;
- Unchecked Exception(运行时异常)虽不强制,但它是调试和加固逻辑的重要信号,体现程序健壮性的分水岭。
继承关系与使用边界
二者都继承自 Throwable,但设计上泾渭分明:
-
Error及其子类属于 JVM 内部契约,应用层不应继承或抛出自定义 Error; -
Exception是开放扩展的,你可以定义自己的业务异常(如InsufficientBalanceException),并纳入统一异常处理流程; - 不要用
catch (Exception e)试图一网打尽 Error——它捕不到(Error 不是 Exception 的子类),也绝不该这么做。










