Java 异常体系

发布时间:2026/7/2 6:02:22
Java 异常体系 下面是一份偏实战向的 Java 异常捕获开发教程从基础语法 → 正确姿势 → 常见坑 → 企业级写法适合日常开发和代码评审使用。一、Java 异常体系概览先搞清“抓什么”Throwable ├── Error 严重错误程序一般无力恢复不捕获 │ ├── OutOfMemoryError │ └── StackOverflowError └── Exception 程序可处理 ├── RuntimeException运行时异常非受检 │ ├── NullPointerException │ ├── IllegalArgumentException │ └── IndexOutOfBoundsException └── 非RuntimeException编译期异常受检 ├── IOException ├── SQLException └── InterruptedException开发原则Error不捕获RuntimeException视业务决定通常不强制捕获受检异常必须处理捕获 or 声明 throws二、try-catch-finally 基础用法1️⃣ 基本结构try { int result 10 / 0; } catch (ArithmeticException e) { System.out.println(除零异常 e.getMessage()); } finally { System.out.println(一定会执行); }finally 的典型用途释放资源IO、数据库连接清理状态finally 中尽量避免 return会覆盖 try/catch 的返回值。三、try-with-resourcesJava 7 自动关闭资源替代繁琐的 finally。try (BufferedReader br new BufferedReader(new FileReader(a.txt))) { System.out.println(br.readLine()); } catch (IOException e) { log.error(读取文件失败, e); }四、异常捕获的正确姿势重点 ⭐1. 不要捕获 Throwable / Exception错误示例try { doSomething(); } catch (Exception e) { e.printStackTrace(); }正确示例catch (IOException e) { log.error(IO异常, e); } 原因会吞掉RuntimeException隐藏 Bug。✅ 2. 不要吞异常空 catch 是大忌catch (Exception e) { // ignore }正确catch (Exception e) { throw new RuntimeException(处理订单失败, e); }3. 保留原始异常异常链try { dao.save(user); } catch (SQLException e) { throw new ServiceException(保存用户失败, e); }否则排查线上问题几乎不可能。4. 早抛晚捕Fail Fast底层发现异常立即抛出上层统一处理Controller / AOP// DAO public void save(User user) { if (user null) { throw new IllegalArgumentException(user不能为null); } } // Controller / Service try { service.save(user); } catch (IllegalArgumentException e) { return Result.fail(e.getMessage()); }五、自定义异常企业项目必备定义业务异常public class BusinessException extends RuntimeException { private final String code; public BusinessException(String code, String message) { super(message); this.code code; } public BusinessException(String code, String message, Throwable cause) { super(message, cause); this.code code; } public String getCode() { return code; } }使用方式if (balance amount) { throw new BusinessException(BALANCE_NOT_ENOUGH, 余额不足); }优点错误码统一管理前端友好便于日志监控六、Spring / Web 项目中的异常处理实战ControllerAdvice 全局异常处理RestControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(BusinessException.class) public ResultVoid handleBusinessException(BusinessException e) { return Result.fail(e.getCode(), e.getMessage()); } ExceptionHandler(Exception.class) public ResultVoid handleException(Exception e) { log.error(系统异常, e); return Result.fail(SYS_ERROR, 系统繁忙请稍后重试); } }✅ 好处Controller 清爽异常集中治理避免重复 try-catch七、日志与异常非常重要正确打日志log.error(创建订单失败, orderId{}, orderId, e);❌ 错误log.error(error: e); // 丢失堆栈 log.error(e.getMessage()); // 无堆栈八、常见坑位总结面试 实战场景正确做法捕获 Exception改为具体异常catch 中 return避免 finally 干扰finally 中 return❌ 严禁空 catch❌吞掉 RuntimeException❌循环中 try-catch❌除非必要用异常控制业务流程❌九、异常使用决策表速查场景处理方式参数校验失败IllegalArgumentException业务规则不满足自定义BusinessExceptionIO / DB 错误捕获后包装为业务异常不可恢复错误抛出 RuntimeExceptionController 层统一捕获并返回 Result工具类抛异常不处理十、一个标准示例推荐写法Service public class OrderService { public Order createOrder(Long userId, Long productId) { if (userId null || productId null) { throw new IllegalArgumentException(参数不能为空); } try { return orderDao.insert(userId, productId); } catch (DataAccessException e) { throw new BusinessException( CREATE_ORDER_FAILED, 创建订单失败, e ); } } }