throw用于主动抛出异常以通知调用方业务异常,推荐继承RuntimeException自定义业务异常,应在参数校验、状态判断等前置环节及时抛出,避免语义模糊的Exception或Throwable。

在 Java 中,throw 关键字用于在业务逻辑中主动抛出异常,让调用方感知到非法状态或业务规则被违反,从而做出相应处理(如提示用户、回滚事务、记录日志等)。
明确抛出检查型或非检查型异常
Java 中异常分两类:检查型异常(Exception 及其子类,但不包括 RuntimeException)和非检查型异常(RuntimeException 及其子类)。业务中常用的是运行时异常,因为无需强制 try-catch 或 throws 声明,更灵活。
- 推荐自定义业务异常继承
RuntimeException,例如InsufficientBalanceException、InvalidOrderStatusException - 避免直接 throw
Exception或Throwable,语义模糊且破坏契约 - 若必须用检查型异常(如集成某些老框架),需在方法签名中声明
throws XxxException
在关键校验点及时 throw 异常
不要等到操作执行完才发现问题。应在参数校验、状态判断、权限验证等前置环节抛出异常,防止无效流程继续执行。
- 示例:用户下单前检查库存
- 示例:校验手机号格式
if (product.getStock() < order.getQuantity()) {
throw new BusinessException("商品库存不足,当前剩余:" + product.getStock());
}
if (!Pattern.matches("^1[3-9]\d{9}$", phone)) {
throw new IllegalArgumentException("手机号格式不正确:" + phone);
}
携带上下文信息,方便定位和处理
抛出异常时应提供清晰、可读的错误消息,并尽量包含关键业务数据(如 ID、金额、状态值),避免空消息或泛泛而谈。
立即学习“Java免费学习笔记(深入)”;
- 用构造函数传入带参消息,而非拼接空字符串
- 可考虑在自定义异常中增加字段(如
errorCode、timestamp),便于统一错误码管理 - 避免在异常消息中暴露敏感信息(如密码、身份证号、内部路径)
配合 try-catch 或全局异常处理器统一响应
主动 throw 不代表要每个地方都 catch。通常建议:
- 在 Controller 层捕获业务异常,转为标准 HTTP 响应(如 400 + 错误码 + 提示)
- 使用
@ControllerAdvice+@ExceptionHandler实现全局异常拦截 - 日志中记录异常堆栈(尤其是非业务类异常),但对
BusinessException可只记 warn 级别 + 消息


















