635 字
2 分钟
Java异常处理最佳实践
在线上被空指针异常搞崩过几次之后,我才真正重视起异常处理的最佳实践。以前觉得try-catch一把梭就完事了,后来发现这样写出来的代码不但不好维护,出了问题还找不到根因。这篇文章总结了我踩过的坑和总结出来的规范。
Java异常处理最佳实践
异常处理的核心原则
1. 只捕获你能处理的异常
不要直接 catch (Exception e) 然后打印个日志就完事。如果你不知道怎么处理,就让它往上抛,让上层代码去处理。
// 不好的做法try { // ...} catch (Exception e) { e.printStackTrace(); // 然后呢?啥也没干}
// 好的做法try { // ...} catch (IOException e) { logger.error("IO error", e); // 进行恢复操作,比如重试}2. 捕获具体的异常类型
别图省事写 catch (Exception e),这样会掩盖真正的错误。
try { // ...} catch (FileNotFoundException e) { logger.error("文件不存在", e);} catch (IOException e) { logger.error("IO异常", e);}3. 使用try-with-resources
所有实现了AutoCloseable的资源都应该用try-with-resources自动关闭。
try (InputStream input = new FileInputStream("file.txt"); OutputStream output = new FileOutputStream("output.txt")) { // 处理输入输出流} catch (IOException e) { logger.error("IO error", e);}4. 不要忽略异常
捕获异常后什么都不做,问题会被隐藏,上线后更难排查。
// 千万不要这样try { // ...} catch (Exception e) { // 什么都不做}5. 不要在循环中捕获异常
异常对象的创建开销很大(要收集堆栈信息),在循环里频繁抛异常性能会急剧下降。
// 不好的做法for (int i = 0; i < 1000; i++) { try { // ... } catch (Exception e) { // ... }}
// 好的做法try { for (int i = 0; i < 1000; i++) { // ... }} catch (Exception e) { // ...}6. 合理使用自定义异常
业务逻辑相关的错误用自定义异常,让代码更清晰。
public class BusinessException extends RuntimeException { private int errorCode;
public BusinessException(int errorCode, String message) { super(message); this.errorCode = errorCode; }
public int getErrorCode() { return errorCode; }}7. 异常信息要清晰
抛出异常时带上足够的上下文信息,方便排查问题。
// 不好的做法throw new NullPointerException();
// 好的做法throw new IllegalArgumentException("用户ID不能为空,当前值:" + userId);8. 正确使用异常链
捕获一个异常抛出另一个异常时,保留原始异常信息。
try { // ...} catch (SQLException e) { throw new BusinessException(500, "数据库操作失败", e);}9. 别用异常控制流程
异常的开销很大,能用条件判断就用条件判断。
// 不好的做法try { return array[index];} catch (ArrayIndexOutOfBoundsException e) { return -1;}
// 好的做法if (index >= 0 && index < array.length) { return array[index];}return -1;常见陷阱
- 过度使用异常——以前组里有个同事喜欢用异常做流程控制,代码跑得慢不说,出了问题还特别难排查
- 忽略异常——捕获了不处理,等于没事找事
- 异常信息不清晰——抛出异常时信息太少,无法定位问题
- 资源泄漏——不用try-with-resources,忘了在finally里关资源
- 不正确的异常链——转换异常时丢了原始异常
💡 实战贴士: 生产环境建议用日志框架(SLF4J + Logback)记录异常,别用
System.out或e.printStackTrace()。而且日志级别要分清楚:业务异常用warn,系统异常用error。这样线上看日志的时候,先看error,再看warn,排查效率高很多。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐
1
Java异常处理详解
Java try-catch是Java最基础的异常处理手段,但什么时候该用受检异常、什么时候该抛RuntimeException,这中间有不少门道值得琢磨。
2
Java日期和时间处理详解
Java Java的日期时间API进化史简直就是一部踩坑史——从Date到Calendar再到java.time包,每次改版都在修复上一版的槽点。这篇文章梳理了各个版本的用法和坑。
3
Java注解处理器详解
Java 编译时注解处理器是项目里做代码生成时的宝藏工具,写一个注解就能自动生成一大堆重复代码,Lombok的@Getter就是这么来的。
4
Java单元测试详解
Java 单元测试曾经是我最懒得写的代码,直到被线上bug教育了几次之后才老老实实补上。JUnit配合Mockito,写测试也可以很愉快。
5
Java NIO详解
Java NIO的Selector模型让我第一次感受到了单线程处理万级连接的魅力。相比传统IO的阻塞读写,Channel加Buffer的组合简直是为高性能网络编程量身定做。






