应避免过深try-catch嵌套,核心是让异常自然流动、职责清晰:用@ControllerAdvice统一处理异常;用try-with-resources自动管理资源;用卫语句提前校验拦截非法输入;用函数式封装屏蔽受检异常。

避免过深的 try-catch 嵌套,核心不是“少写 catch”,而是让异常流动更自然、职责更清晰——把错误处理从业务逻辑里剥离开,用结构化手段替代层层兜底。
用统一异常处理器接管全局
Spring 项目中,90% 的业务方法无需写任何 try-catch。只需定义一个 @ControllerAdvice 类,集中捕获自定义异常或底层异常:
- 底层服务抛出
new BusinessException("余额不足", e),带原始 cause - 全局处理器根据异常类型返回标准响应体,同时记录完整堆栈(
e.getCause()可追溯源头) - 控制器层只管调用
service.transfer(...),不关心怎么捕获
把资源管理交给 try-with-resources
涉及文件、数据库连接、网络流等场景,嵌套常源于手动 close 的防御写法。Java 7+ 的 try-with-resources 能自动释放资源,且支持多资源声明:
- 写法:
try (BufferedReader br = new BufferedReader(...); InputStream is = ...) { ... } - 即使读取中途抛异常,br 和 is 仍会被依次关闭,无需 finally 或嵌套 try
- 资源类必须实现
AutoCloseable,主流 IO 和 JDBC 类库都已支持
提前校验 + 卫语句拦截非法输入
很多嵌套其实源于“等出错了再处理”,而真正该做的是:在进入复杂流程前就拒绝无效状态:
立即学习“Java免费学习笔记(深入)”;
- 循环前检查集合非空、配置项存在、外部服务已就绪
- 参数校验失败直接抛
IllegalArgumentException,不进 for 或 while - 例如:
if (files == null) throw new IllegalArgumentException("文件列表为空")
用函数式封装屏蔽受检异常干扰
面对 Files.readString() 这类抛 IOException 的 API,不必在每处加 try,可封装成“无异常”接口:
- 定义
ThrowingFunction<t r></t>接口,再写工具方法unchecked()将其转为Function - 使用时:
list.stream().map(unchecked(Files::readString)).collect(...) - 异常仍会以
RuntimeException形式向上冒泡,但业务代码缩进干净、无 try 块污染


















