java项目级异常处理需分层设计:受检异常必须显式处理,运行时异常应修复而非捕获;资源操作强制使用try-with-resources;catch须记录、转换或降级,禁用空catch和泛捕获;finally仅限无副作用的资源清理。

Java项目级异常处理不是堆砌try-catch,而是建立分层、可维护、有语义的响应机制。核心在于:受检异常必须处理,运行时异常应修复而非捕获;资源操作优先用try-with-resources;全局兜底不替代局部精准捕获。
明确异常类型边界,避免泛捕获
受检异常(如IOException、SQLException)是编译强制的外部风险,必须显式处理;运行时异常(如NullPointerException、IllegalArgumentException)反映代码缺陷,应通过校验和逻辑修正预防,而非靠catch掩盖。
- 禁止写 catch (Exception e) 或 catch (Throwable t) —— 会吞掉OOM、栈溢出等致命错误
- 多异常捕获时,子类异常写在父类前:先 FileNotFoundException,再 IOException
- Java 7+支持多异常合并写法:catch (IOException | SQLException e),但仅限语义相近、处理方式一致的情况
资源操作统一用try-with-resources
文件流、数据库连接、网络Socket等实现了AutoCloseable接口的资源,必须用try-with-resources替代手动finally关闭——它自动调用close(),且能抑制多个异常中的次要异常。
- 正确写法:try (FileInputStream fis = new FileInputStream("a.txt")) { ... }
- 错误写法:在finally里手动调用fis.close(),易漏、易NPE、close()本身还可能抛异常
- 若需自定义关闭逻辑(如回滚事务),仍应在try-with-resources内完成,不要退回到传统finally
catch块必须做三件事之一
空catch或只写e.printStackTrace()是严重反模式。每个catch必须明确目的:记录、转换、或降级恢复。
- 记录上下文日志:用SLF4J,带上关键业务字段,如 log.error("支付回调验签失败,orderNo={}", orderNo, e)
- 转换为业务异常:将底层技术异常包装成语义清晰的自定义异常,如 throw new PaymentVerifyException("验签失败", e)
- 局部降级返回:仅当有合理备选路径时,如缓存失效时返回默认值、远程调用超时后走本地模拟逻辑
finally只做资源清理,绝不return或抛新异常
finally是“收尾专用通道”,不是控制分支,更不是返回出口。
- 允许的操作:关闭流、释放锁、清空ThreadLocal、归还数据库连接
- 禁止操作:return(会覆盖try/catch中已确定的返回值)、throw new RuntimeException()(会掩盖原始异常堆栈)
- 真正需要兜底释放的场景,90%以上可用try-with-resources替代;剩余场景用finally时,确保内部只调用无副作用的close()类方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











