规范Java异常处理需坚持资源安全、意图明确、可追溯、不掩盖四原则:优先用try-with-resources管理资源;多catch按继承关系从具体到宽泛排列;每个catch必须记录日志、转换异常或局部降级;finally仅作无异常风险的收尾操作。

规范的 Java 异常处理不是套一个固定代码块,而是围绕“资源安全、意图明确、可追溯、不掩盖”四个核心来组织。标准模板不是死格式,而是有逻辑分层的结构化实践。
资源清理:优先用 try-with-resources
凡涉及流、连接、锁等需显式释放的资源,必须用 try-with-resources,而不是传统 try-catch-finally。
- ✅ 正确写法:try (FileInputStream fis = new FileInputStream("a.txt")) { /* 业务逻辑 */ } —— 自动关闭,无需判空、无 NPE 风险、close() 异常也被正确抑制
- ❌ 错误写法:在 finally 里手动调用 fis.close() —— 易漏、易空指针、close 本身可能抛异常导致原始异常被覆盖
- ⚠️ 特殊情况(如需事务回滚):仍应在 try-with-resources 内完成自定义收尾,不要退回到老式 finally 块
捕获逻辑:子类优先 + 分类响应
多 catch 必须按继承关系从具体到宽泛排列,每个分支要有明确目的,不能只为“不崩”而兜底。
- ✅ 推荐顺序:catch (SQLException e) → catch (IOException e) → catch (IllegalArgumentException e) → catch (RuntimeException e)
- ✅ 合并同类处理(Java 7+):catch (IOException | SQLException e) —— 仅当它们无继承关系且处理逻辑完全一致时使用
- ❌ 禁止把 Exception 放最前,或只写一个 catch (Exception e) 吞掉所有异常
catch 内部:三选一,拒绝静默
每个 catch 块必须做且仅做以下三件事之一,不可省略、不可混合:
立即学习“Java免费学习笔记(深入)”;
- ? 记录上下文日志:用 SLF4J,带关键业务字段,如 log.error("支付验签失败, orderNo={}", orderNo, e)
- ? 转换为业务异常:包装成语义清晰的自定义异常,如 throw new PaymentVerifyException("验签失败", e)
- ? 局部降级恢复:仅当存在合理备选路径时,如缓存失效返回默认值、远程超时走本地模拟逻辑
finally 和 return:严守边界
finally 是纯收尾通道,不是控制分支,更不是返回出口。
- ✅ 允许操作:关闭流(但应优先用 try-with-resources)、释放锁、清空 ThreadLocal、归还数据库连接
- ❌ 禁止操作:return(会覆盖 try/catch 已确定的返回值)、throw new RuntimeException()(会掩盖原始异常堆栈)
- ⚠️ 注意:即使 finally 中发生异常,也会压制 try 或 catch 中已抛出的异常 —— 所以它只该做“确定不会出错”的事


















