你真的知道 Java 里的 Exception 和 Error 有啥不同吗?

原文来自于:zha-ge.cn/java/24

你真的知道 Java 里的 Exception 和 Error 有啥不同吗?

一个看似简单的面试题

那天和小李聊天,他刚面试回来,一脸郁闷:"面试官问我 Exception 和 Error 的区别,我说了半天继承关系,结果他说答得太浅显了。这不都是异常吗,有啥区别?"

我笑了笑,想起自己当年也是这么想的。直到那次生产环境的惨案...

那个让我印象深刻的周五下午

记得那是个普通的周五,我正准备下班,突然运维小哥慌张地跑过来:"系统挂了!用户都在投诉!"

打开监控一看,服务器内存爆了,日志里全是这样的信息:

java 复制代码
java.lang.OutOfMemoryError: Java heap space
    at java.util.ArrayList.grow(ArrayList.java:267)
    at com.example.service.DataProcessor.processLargeData(DataProcessor.java:45)

我当时第一反应是用 try-catch 包住这段代码,结果发现根本捕获不到!

java 复制代码
try {
    // 处理大量数据
    List<String> hugeList = new ArrayList<>();
    for (int i = 0; i < Integer.MAX_VALUE; i++) {
        hugeList.add("data_" + i);
    }
} catch (Exception e) {
    // 这里永远不会执行!
    logger.error("处理失败", e);
}

踩坑瞬间

那一刻我才意识到,OutOfMemoryError 压根不是 Exception,而是 Error!

查了源码才发现,Java 的异常体系是这样的:

  • Throwable (老祖宗)
    • Error :系统级错误,程序无法处理
      • OutOfMemoryError(内存不足)
      • StackOverflowError(栈溢出)
      • NoClassDefFoundError(找不到类)
    • Exception :程序级异常,可以被处理
      • RuntimeException(运行时异常)
      • 检查异常(编译时必须处理)

真正的区别在哪里?

经过那次事故,我总结了三个本质区别:

1. 处理思路完全不同

Exception 是"可以商量的":

java 复制代码
try {
    int result = 10 / 0;  // ArithmeticException
} catch (ArithmeticException e) {
    // 可以优雅处理,比如返回默认值
    return -1;
}

Error 是"不讲道理的",你只能接受现实,最多记录一下:

java 复制代码
// Error 一般不建议捕获,但如果非要捕获:
try {
    recursiveMethod();  // 可能导致 StackOverflowError
} catch (Error e) {
    // 只能记录,然后程序该挂还是会挂
    logger.fatal("系统崩溃", e);
    System.exit(1);
}

2. 产生原因天差地别

类型 产生原因 典型场景
Exception 业务逻辑问题、外部环境变化 文件不存在、网络超时、参数错误
Error JVM 或系统资源问题 内存耗尽、栈空间不足、类加载失败

3. 影响范围不一样

  • Exception:通常影响单个操作或请求
  • Error:往往影响整个应用甚至 JVM

经验启示

那次生产事故后,我养成了几个习惯:

  1. 监控内存使用:定期检查堆内存、栈深度
  2. 区别对待异常:Exception 用于业务处理,Error 用于系统预警
  3. 谨慎捕获 Error:除非做日志记录,否则不要轻易 catch Error

最重要的是,理解了这个区别后,面对异常时的思考方式完全变了:

  • 遇到 Exception:这个问题我能解决吗?怎么优雅处理?
  • 遇到 Error:系统哪里出问题了?需要扩容还是优化?

写在最后

现在再有人问我 Exception 和 Error 的区别,我不会只说继承关系了。它们就像感冒和骨折的区别:

  • Exception 像感冒,吃点药、休息一下就好了
  • Error 像骨折,得上医院,不处理会要命

下次遇到这个问题,你知道怎么回答了吗?

相关推荐
依_旧2 小时前
MySQL下载安装配置(超级超级入门级)
java·后端
淘源码d3 小时前
什么是医院随访系统?成熟在用的智慧随访系统源码
java·spring boot·后端·开源·源码·随访系统·随访系统框架
程序猿阿越3 小时前
Kafka源码(七)事务消息
java·后端·源码阅读
m0_748248023 小时前
C++20 协程:在 AI 推理引擎中的深度应用
java·c++·人工智能·c++20
笑我归无处3 小时前
强引用、软引用、弱引用、虚引用详解
java·开发语言·jvm
02苏_3 小时前
秋招Java面
java·开发语言
爱吃甜品的糯米团子4 小时前
详解 JavaScript 内置对象与包装类型:方法、案例与实战
java·开发语言·javascript
程序定小飞4 小时前
基于springboot的学院班级回忆录的设计与实现
java·vue.js·spring boot·后端·spring
攀小黑4 小时前
基于若依-内容管理动态修改,通过路由字典配置动态管理
java·vue.js·spring boot·前端框架·ruoyi
青云交5 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用
java·spark·lstm·可视化·java 大数据·空气质量监测·污染溯源