Error 不该捕获,因其标志 JVM 失控(如 OutOfMemoryError、StackOverflowError),捕获反而掩盖问题;Exception 中仅「业务可响应」的 checked Exception(如 IOException)需强制处理,RuntimeException(如 NullPointerException)应修复而非捕获。

Exception 和 Error 都能被 throw,但 catch Error 几乎没意义
Java 异常体系里,Exception 和 Error 都继承自 Throwable,所以语法上都能被抛出、也能被 catch。但关键区别不在“能不能捕获”,而在于“该不该捕获”——Error 是 JVM 自身崩溃边缘的信号,程序逻辑已失去控制权。
-
OutOfMemoryError发生时,JVM 连新对象都分配不出,你写的catch块甚至可能因内存不足而无法执行 -
StackOverflowError一出现,调用栈已经爆满,连catch的入口方法都压不进栈 - 真去
catch (Error e),往往只是掩盖问题,让程序在不可靠状态下继续跑,反而更容易丢数据或写坏状态
什么时候该关注 Exception?看它是不是「业务可响应」的异常
不是所有 Exception 都值得处理,核心判断标准是:这个异常发生后,程序是否还能根据上下文做出合理决策?
-
FileNotFoundException:文件不存在 → 可提示用户重选路径、加载默认配置、或记录日志后跳过 -
SQLException(如连接超时):可重试、降级查缓存、或返回友好错误码 -
NullPointerException:属于RuntimeException,说明代码有空值漏洞,应修复逻辑而非捕获——捕获它就像给漏水的水管贴胶带
编译器强制你处理的,一定是 checked Exception
Java 编译器只对 Exception 的子类(且非 RuntimeException 及其子类)做编译期检查。这不是设计偏好,而是契约声明:调用方必须明确面对这种异常的后果。
- 比如
new FileInputStream("a.txt")必须try-catch或throws IOException,因为文件 I/O 天然依赖外部状态,无法在编译时保证存在 - 而
Integer.parseInt("abc")抛NumberFormatException(RuntimeException子类),编译器不管——它反映的是输入校验缺失,该在调用前加if判断,而不是靠catch救火 - 滥用
throws Exception会把问题甩给上层,最终往往变成没人处理的“静默异常”
别在日志里把 Error 当成普通异常打出来就完事
看到 java.lang.OutOfMemoryError: Java heap space 这类日志,第一反应不该是“加个 try-catch”,而是立刻检查堆内存配置、对象泄漏点、大集合未清理等根本原因。
- JVM 在抛
Error前通常已尝试 GC 多次失败,此时任何业务逻辑都不可信 - 如果线上频繁出现
NoClassDefFoundError,大概率是类加载器隔离问题或 jar 包冲突,不是改代码能解决的 - 监控系统里把
Error和Exception混在一起告警,会导致真正需要人工介入的严重故障被淹没
RuntimeException 当成 checked Exception 来兜底处理,或者反过来,对本该预防的 IOException 放任不管——区分依据从来不是“严重不严重”,而是“这个异常发生时,你的代码有没有能力做有意义的事”。

















