空捕获是Java中典型反模式,应通过静态检查工具(如SonarQube规则S2221、Checkstyle)、统一异常处理模板、try-with-resources、异常分类及决策树文档来杜绝。

空捕获(即 catch 块中既不记录日志,也不重新抛出异常,甚至不作任何处理)是 Java 等语言中典型的反模式,它会让错误静默消失,极大增加排查难度。防止这类问题,关键在于建立规范、借助工具和养成习惯。
用静态检查工具自动拦截
大多数现代 IDE 和构建流程都支持静态分析,可配置规则来识别空 catch 块:
- 在 SonarQube 或 SonarLint 中启用规则
S1166("Exception handlers should preserve the original exception")或S2221("Empty catch block") - 使用 Checkstyle 配置
EmptyCatchBlock检查,支持自定义忽略特定合法场景(如InterruptedException的中断标记清除) - 在 CI 流程中强制失败:一旦扫描发现空
catch,构建直接报错,阻断提交
统一异常处理模板与代码审查清单
团队应明确“什么也不做”不是合法选项。所有 catch 块必须满足至少一项:
- 调用日志框架(如
log.error("业务操作失败", e)),且日志包含上下文信息(如用户 ID、订单号) - 转换为更明确的业务异常并抛出(
throw new BusinessException("支付超时,请重试", e)) - 执行确定的补偿动作(如关闭资源、回滚状态),并在注释中清晰说明“此处吞异常是安全的,因为……”
代码审查时,把“该 catch 是否有可验证的处理逻辑?”列为必检项。
用 try-with-resources + 明确的异常分类代替裸 try-catch
很多空捕获源于对资源管理或受检异常的误处理。优先使用:
-
try-with-resources自动关闭资源,减少因close()抛异常而写空catch的冲动 - 将受检异常在方法签名中声明抛出(
throws IOException),而非在底层强行吞掉 - 对确实需屏蔽的异常(如
NumberFormatException在解析可选参数时),用带说明的单行日志:log.debug("忽略无效的版本号格式: {}", input);
建立“异常处理决策树”文档
给常见异常类型配处理指引,降低随意性。例如:
- NullPointerException → 不应捕获,应修复 NPE 根源(加判空/Optional)
-
InterruptedException → 必须响应中断(恢复中断状态
Thread.currentThread().interrupt()或抛出InterruptedException) - IOException(网络/文件) → 记录完整堆栈 + 上下文,并根据 SLA 决定重试或降级
把这份文档嵌入到内部开发 Wiki,并在新成员培训中重点讲解。


















