学会 Java 异常处理,其实没你想的那么难

原文来自于:zha-ge.cn/java/25

学会 Java 异常处理,其实没你想的那么难

那个让我崩溃的深夜

记得刚工作那会儿,有个深夜我被一通电话叫醒:"系统又崩了!用户投诉说支付页面打不开!"我迷迷糊糊地爬起来,打开电脑一看日志,满屏的红色异常堆栈信息,像是在嘲笑我这个菜鸟。

那时候的我,对异常的理解就是"能跑就行",碰到异常就直接 try-catch 一把梭,catch 块里要么空着,要么随便打个日志。直到那个深夜,我才意识到:异常处理不是用来掩盖问题的,而是用来优雅地解决问题的。

从"鸵鸟心态"到"正面刚"

最开始,我写代码是这样的:

java 复制代码
public void transferMoney(String fromAccount, String toAccount, BigDecimal amount) {
    try {
        // 检查余额
        // 扣款
        // 转账
        // 记录日志
    } catch (Exception e) {
        // 啥也不干,假装没看见
    }
}

看起来没报错,但用户的钱莫名其妙消失了,客服电话被打爆。老大看了我的代码后,语重心长地说:"小伙子,你这是在玩火啊!"

踩坑瞬间:异常的"连环杀"

后来我开始认真对待异常,但又走进了另一个极端------什么都往上抛:

java 复制代码
public UserInfo getUserInfo(Long userId) throws SQLException, IOException, ParseException {
    // 查数据库可能抛 SQLException
    // 读配置文件可能抛 IOException
    // 解析数据可能抛 ParseException
    return userInfo;
}

结果调用链上每个方法都要处理一堆异常,代码变得臃肿不堪。更要命的是,调用方根本不知道该怎么处理这些异常,只能继续往上抛,最终形成了"异常传递链"。

转机:学会"分而治之"

真正的转机来自一次 Code Review。技术经理指着我的代码说:"异常处理要有层次感,不同的异常要用不同的策略。"

他教我把异常分成三类:

异常类型 处理策略 典型场景
可恢复异常 重试或降级 网络超时、数据库连接失败
业务异常 转换为友好提示 余额不足、用户不存在
系统异常 记录日志并告警 内存溢出、磁盘空间不足

优雅解决:自定义异常体系

现在我的异常处理是这样的:

java 复制代码
public class PaymentService {
  
    public PaymentResult transfer(TransferRequest request) {
        try {
            validateRequest(request);
            return doTransfer(request);
        } catch (InsufficientBalanceException e) {
            return PaymentResult.fail("余额不足,请充值后重试");
        } catch (AccountNotFoundException e) {
            return PaymentResult.fail("账户不存在");
        } catch (NetworkException e) {
            // 网络异常,重试3次
            return retryTransfer(request, 3);
        }
    }
}

关键在于建立了清晰的异常层次:

  • BusinessException:业务异常,需要给用户友好提示
  • SystemException:系统异常,需要记录详细日志
  • RetryableException:可重试异常,自动重试机制

经验启示:异常处理的"三板斧"

经过几年的摸爬滚打,我总结出异常处理的"三板斧":

1. 快速失败原则

发现问题立即抛出异常,不要让错误数据继续传递。宁可程序停下来,也不要产生脏数据。

2. 就近处理原则

谁最了解异常的含义,就让谁来处理。数据库异常在 DAO 层处理,业务异常在 Service 层处理。

3. 用户友好原则

永远不要把技术异常直接抛给用户。NullPointerException 要转换成"数据获取失败",SQLException 要转换成"系统繁忙,请稍后重试"。

写在最后

异常处理就像开车时的安全带,平时可能感觉不到它的存在,但关键时刻能救命。好的异常处理不是让程序不出错,而是让程序出错时能够体面地处理。

现在每当有新人问我异常处理的秘诀,我都会告诉他们:异常不可怕,可怕的是对异常视而不见。 与其花时间调试为什么程序崩溃,不如一开始就把异常处理做好。

记住:写代码容易,写好代码难,但写出能在生产环境稳定运行的代码,那才是真正的本事。

相关推荐
.Bryce.2 小时前
你了解 Blackboard(黑板系统)吗?听说过基于黑板系统实现的智能体吗?
java·网络·gpt·php·agent·codex·黑板系统
猿究院_夏燊8 小时前
Spring Bean 生命周期
java·后端·spring
Wang's Blog9 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
信誓旦旦的程序猿9 小时前
【Python量化实战宝典 #08】可转债与债券接口手册:转股价·溢价率·纯债价值(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
砚底藏山河9 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
Jlzn88889 小时前
华东电芯分选通道数怎么配才不堵线
java·人工智能·架构·自动化·制造
香吧香10 小时前
GRPC连接机制---长连接分析
java·网络与传输协议
我是人✓10 小时前
SpringBoot项目的五种创建方式
java·spring boot·后端
Wang's Blog10 小时前
Java 项目实战: 交友项目 - 阿里云 OSS 入门案例:从创建 Bucket 到上传拿到可访问 URL
java·阿里云·交友
裕晟资质规划11 小时前
三类涉密资质延续时限差异分析:军工60日与集成印制3个月的边界
java·服务器·前端·网络·安全