不建议捕获Exception或Throwable,因其会掩盖NullPointerException等代码缺陷和OutOfMemoryError等JVM严重错误,导致数据不一致、死锁或静默失败;应分层精准捕获具体异常,在最外层统一兜底并记录上下文日志后包装抛出。

不建议捕获所有异常类型,核心在于它会模糊错误本质、阻碍问题定位、破坏程序可靠性。真正需要处理的不是“有没有异常”,而是“什么异常、在哪发生、该怎么响应”。
捕获Exception会吞掉本该暴露的bug
Exception是所有检查型和非检查型异常的父类,包括NullPointerException、IllegalArgumentException这类明显由代码缺陷引发的运行时异常。一旦用catch (Exception e)兜底,这些本应在开发阶段就暴露的问题就被静默掩盖。
- 本地测试正常,上线后空指针导致关键逻辑跳过,数据不一致却无日志可查
- 数组越界被吃掉,后续操作基于非法状态继续执行,引发更隐蔽的连锁错误
- 调用方无法感知底层失败,误以为操作成功,造成业务语义失真
捕获Throwable等于假装能处理JVM崩溃
Throwable包含Error(如OutOfMemoryError、StackOverflowError)和Exception两支。Error代表JVM已无法维持基本运行的严重故障,不是应用代码能“恢复”的场景。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 捕获OutOfMemoryError后继续执行,可能因内存不足而新建对象失败、线程卡死、数据写入不完整
- 递归过深触发StackOverflowError,捕获后强行续跑,极易再次崩溃或返回null值污染下游
- ID E和静态分析工具(如SpotBugs)会直接标红catch (Throwable t),这不是风格提醒,是风险拦截信号
替代方案:分层精准捕获 + 统一兜底
异常处理的关键不是“要不要捕获”,而是“在哪捕、捕什么、怎么响”。宽泛捕获的替代路径很清晰:
立即学习“Java免费学习笔记(深入)”;
- 业务方法中只捕获明确知道如何处理的具体异常,比如HTTP调用捕获TimeoutException、文件读取捕获FileNotFoundException
- 资源操作优先用try-with-resources,避免手动管理close带来的异常干扰
- 参数校验提前做(Objects.requireNonNull、正则预检),从源头减少RuntimeException抛出
- 真正需要兜底的地方仅限最外层——Spring用@ControllerAdvice统一转换,Servlet用doGet/doPost末尾捕获,且必须记录完整堆栈并包装为业务异常再抛出
不处理比乱处理更安全
很多异常本就不该在当前层级处理。比如Service层遇到SQLException,若无重试或降级逻辑,最佳做法是让异常向上抛出,交由事务管理器回滚;Repository层出现IO异常,也不应自行吞掉,而应传递给上层决定是否重试或返回默认值。
- 吞掉异常(空catch块)比不捕获更危险——它让程序在错误状态下继续运行
- 哪怕只是e.printStackTrace(),也丢失了上下文(如请求ID、用户信息)、日志级别和结构化字段
- 正确做法是:记录带上下文的ERROR日志 + 包装为语义明确的新异常(throw new BusinessException("支付失败", e))

















