Java异常处理别再瞎搞了!阿里大神总结的 9 种最佳实践,让你的代码更健壮!

大家好,我是大华。 昨天被迫帮同事改bug,看到他的代码我差点心梗:

java 复制代码
try {
    // 业务代码NN行
} catch (Exception e) {
    e.printStackTrace();
}

这异常处理写得,真是老太太钻被窝------哈哈! 同事还说:"代码能跑就行,要啥自行车啊?"

但问题是,这种写法就像是在代码里埋了颗地雷,说不准什么时候就炸了。 所以这篇文章我把从阿里大神那偷师的9个异常处理分享给大家,保准让你的代码更健壮!

1. 别抓了异常又扔掉!

这种就是抓了异常又不处理的:

java 复制代码
// 错误示范
try {
    userService.save(user);
} catch (IOException e) {
    e.printStackTrace(); 
}

正确做法

java 复制代码
try {
    userService.save(user);
} catch (IOException e) {
    log.error("保存用户信息失败,用户ID:{}", user.getId(), e);
    throw new BusinessException("保存用户失败,请重试");
}

记日志是为了排查问题,重抛异常是让上游知道到底是哪里出错了!

2. 精确捕获异常

很多新手爱用Exception一把梭:

java 复制代码
// 错误示范
try {
    // 各种操作
} catch (Exception e) { // 抓得太宽了
    // 处理异常
}

正确写法

java 复制代码
try {
    // 业务代码
} catch (FileNotFoundException e) {
    // 处理文件不存在
} catch (IOException e) {
    // 处理IO问题
} catch (SQLException e) {
    // 处理数据库问题
}

不同的异常不同的处理方式!

3. finally里不要乱写!

这个代码看的让人血压直接升高:

java 复制代码
try {
    // 业务代码
    return true;
} finally {
    return false; // 居然在finally里返回!
}

finally里只做清理工作

java 复制代码
InputStream input = null;
try {
    input = new FileInputStream("file.txt");
    // 处理文件
} finally {
    if (input != null) {
        try {
            input.close(); // 只做资源清理
        } catch (IOException e) {
            log.warn("关闭流失败", e);
        }
    }
}

4. 抛异常要带上原始信息!

这样抛异常等于没抛:

java 复制代码
// 错误示范
try {
    // 代码
} catch (IOException e) {
    throw new BusinessException("操作失败"); // 原始异常信息丢了!
}

应该包装原始异常

java 复制代码
try {
    // 代码
} catch (IOException e) {
    throw new BusinessException("文件操作失败", e); // 把e传进去
}

这样堆栈信息才不会断!

5. 别用异常做流程控制!

这是我见过最骚的操作:

java 复制代码
// 错误示范
try {
    while (true) {
        // 靠异常跳出循环!
        list.get(index);
        index++;
    }
} catch (IndexOutOfBoundsException e) {
    // 循环结束
}

正确写法

java 复制代码
for (String item : list) {
    // 正常循环处理
    // 有问题跳出即可
}
// 或者
for (int i = 0; i < list.size(); i++) {
    // 也是正常的
    // 有问题跳出即可
}

异常处理其实还是很耗性能的,不能啥都用异常来抛出!

6. 自定义异常更有意义!

别老是抛RuntimeException

java 复制代码
// 不太好的做法
if (user == null) {
    throw new RuntimeException("用户不存在");
}

自定义异常更清晰

java 复制代码
// 先定义业务异常
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

// 使用时
if (user == null) {
    throw new UserNotFoundException("用户ID不存在:" + userId);
}

这样一看就知道是什么问题!

7. 异常信息要能看懂!

这种异常信息看了想冒火:

java 复制代码
// 错误示范
throw new Exception("出错啦");
throw new Exception("系统错误");

好的异常信息应该这样

java 复制代码
// 好的异常信息应该包含关键信息
throw new ValidationException(
    String.format("用户手机号格式错误:%s,请输入11位数字", phoneNumber)
);

throw class BalanceNotEnoughException(
    String.format("用户余额不足,用户ID:%s,当前余额:%.2f,需要金额:%.2f", 
        userId, currentBalance, requiredAmount)
);

看到异常就知道具体什么问题,bug该怎么修!

8. 别忘了异常的性能!

异常处理是昂贵的,别在频繁调用的地方去使用:

java 复制代码
// 常用的数据类型转换(错误示范)
try {
    return Integer.parseInt(str);
} catch (NumberFormatException e) {
    return defaultValue;
}

对于可预见的错误,应该先检查

java 复制代码
// 先检查再转换,性能更好
if (str == null || !str.matches("\\d+")) {
    return defaultValue;
}
return Integer.parseInt(str);

9. 统一异常处理!

最后一点,也是最重要的一点:统一处理异常。

尽量不要在代码里到处try-catch:

java 复制代码
// Controller中的方法
@PostMapping("/create")
public Result createUser(@RequestBody User user) {
    try {
        userService.create(user);
        return Result.success();
    } catch (UserExistException e) {
        log.warn("用户已存在", e);
        return Result.error("用户已存在");
    } catch (Exception e) {
        log.error("创建用户失败", e);
        return Result.error("系统繁忙");
    }
}

用@ControllerAdvice统一处理

java 复制代码
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public Result handleBusinessException(BusinessException e) {
        log.warn("业务异常", e);
        return Result.error(e.getMessage());
    }
    
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result handleException(Exception e) {
        log.error("系统异常", e);
        return Result.error("系统繁忙,请稍后重试");
    }
}

这样代码清爽多了,异常处理逻辑都在一起!

总结一下

好的异常处理不是炫技,而是让你的代码:

  • 更健壮:不会轻易崩溃
  • 更可读:异常信息清晰明了
  • 易维护:问题定位快

这9条,不是为了看起来专业,而是为了:线上出问题时,你能第一时间定位,而不是在那干瞪眼。 把这 9 条做成团队规范,省下的不只是时间,还有头发。 ------ 写给每一个被异常坑过的 Java 程序员

我是大华,专注分享前后端开发的实战笔记。关注我,少走弯路,一起进步!

📌往期精彩

《Elasticsearch 太重?来看看这个轻量级的替代品 Manticore Search》

《只会写 Mapper 就敢说会 MyBatis?面试官:原理都没懂》

《别学23种了!Java项目中最常用的6个设计模式,附案例》

《写给小公司前端的 UI 规范:别让页面丑得自己都看不下去》

《Vue3+TS设计模式:5个真实场景让你代码更优雅》

相关推荐
huaiqiongying9 小时前
Springboot3+SpringSecurity6Oauth2+vue3前后端分离认证授权-客户端
java·vue.js·spring boot
杨杨杨大侠9 小时前
手搓责任链框架 5:执行流程
java·spring·github
武子康9 小时前
大数据-87 Spark 实现圆周率计算与共同好友分析:Scala 实战案例
大数据·后端·spark
Metaphor6929 小时前
Java 压缩 PDF 文件大小:告别臃肿,提升效率!
java·经验分享·pdf
zjjuejin9 小时前
Docker 数据卷管理完全指南:持久化数据的艺术与科学
后端·docker
成书平9 小时前
简单入门 mcp server
后端
m0_709788629 小时前
单片机点灯
java·前端·数据库
野犬寒鸦9 小时前
力扣hot100:螺旋矩阵(边界压缩,方向模拟)(54)
java·数据结构·算法·leetcode
追逐时光者9 小时前
.NET 使用 CsvHelper 快速读取和写入 CSV 文件
后端·.net