跳到主要内容

Java 异常处理,别让 catch 吞掉真正的现场

· 阅读需 2 分钟
一介布衣
全栈开发者

Java 项目里很容易出现一种“看上去很稳”的异常处理:每一层都在 catch,每一层都在包一层自己的提示,最后用户确实看不到原始异常了,但开发排查时也很难再看到真正的现场。
2017 年我在处理一些线上问题时,对这一点的体会越来越深。

为什么异常被“处理”了,问题反而更难查

因为很多 catch 做的不是恢复,而只是吞信息。
最常见的情况是:

  • 只打印一句“操作失败”
  • 重新抛出新异常却不带原始上下文
  • 直接返回默认值,导致问题被延后暴露

代码表面上像很周全,实际上是在把有价值的线索一层层抹掉。

我后来更愿意怎么处理异常

我不反对 catch,但更在意它到底在做什么。
如果当前层没有能力恢复问题,那更好的动作通常是:

  • 保留原始异常
  • 补充必要业务上下文
  • 让更合适的上层统一收口

这样既不会把现场丢掉,也不会让异常一路裸奔到最顶层。

小结

Java 异常处理真正难的,不是会不会 catch,而是有没有在 catch 时保住问题现场。
对排查来说,最怕的不是异常多,而是异常被处理得“看起来没问题”。2017 年之后我越来越认同,能恢复就恢复,不能恢复就别吞。

如果一定要在中间层改写异常,我也更愿意只补业务上下文,不把原始异常链断掉。
因为真正帮助排查的,从来不只是“当前模块想表达什么”,还包括最底层到底抛了什么、在哪个条件下抛的。把这条链留住,异常信息才像证据,而不是只剩一句态度化的提示。