Java异常不应替代流程控制,需区分可恢复/不可恢复错误及业务约束,用Result/Optional处理预期失败,用RuntimeException表达非预期故障,用Checked Exception处理外部依赖失败,并通过全局异常处理器、语义化异常链和策略模式收敛分支。

Java异常处理不该成为流程控制的替代品,减少分支判断的关键在于让异常真正用于“异常场景”,而非常规业务逻辑分流。设计上要区分可恢复错误、不可恢复错误和业务规则约束,再配合合理的异常类型选择与分层处理策略。
明确异常分类,避免用异常做流程跳转
很多分支判断源于把业务校验失败(如参数不合法、余额不足)抛成运行时异常,再用try-catch捕获后走不同分支。这违背异常本意,也掩盖真实错误语义。
- 参数校验、业务规则不满足等预期内情况,应返回Result
、Optional或状态码,不抛异常 - 空指针、数组越界、资源不可用等非预期故障,才用RuntimeException或其子类表达
- 需显式处理的外部依赖失败(如网络超时、数据库连接断开),定义受检异常(Checked Exception),强制调用方决策
统一异常处理入口,收敛分支逻辑
把分散在各处的if-else异常处理,收口到全局异常处理器(如Spring的@ControllerAdvice),让业务代码专注主路径。
- Controller层只抛出语义清晰的自定义异常(如UserNotFoundException、InsufficientBalanceException)
- 全局处理器根据异常类型映射HTTP状态码、错误码和提示信息,统一响应格式
- 避免在Service里反复写try-catch来“处理”业务异常,那只是把分支从if搬到了catch里
善用异常链与构造语义化信息
减少分支的前提是异常本身能准确传递上下文,让上层无需再判断“为什么失败”,直接按类型响应。
立即学习“Java免费学习笔记(深入)”;
- 抛异常时带原始cause(new ServiceException("转账失败", e)),保留堆栈链路
- 自定义异常字段补充业务信息(如订单号、用户ID),避免日志里拼接字符串
- 不用泛化的Exception或RuntimeException,而是细分如ValidationException、ExternalApiException
用策略模式替代异常驱动的分支
当确实存在多种失败后处理方式(如重试、降级、告警),别靠catch多个异常类型来分支,改用策略注册+查找机制。
- 定义FailureHandler接口,按异常类型注册对应处理器
- 统一failover方法根据异常class查找并执行handler,主流程无分支
- 新增处理逻辑只需加实现类+注册,不修改原有if/try结构
基本上就这些。核心不是少写catch,而是让异常回归“意外事件”的定位——该用条件判断的别扔给异常,该用异常表达的别硬塞进if。设计清楚了,分支自然就少了。










