自定义异常需继承RuntimeException或Exception,业务逻辑中应在入口或关键点校验后立即throw,优先选RuntimeException以避免强制处理,同时提供含message和cause的构造函数。

在 Java 业务逻辑中主动抛出自定义异常,核心就两点:先定义好异常类,再在合适位置用 throw 关键字抛出。关键不是“能不能抛”,而是“什么时候抛、为什么抛、抛得是否清晰”。
定义自定义异常类要继承 Throwable 的子类
通常选择继承 RuntimeException(运行时异常,无需强制 try-catch)或 Exception(受检异常,调用处必须处理)。业务场景中多数用前者,更轻量、更符合实际开发习惯。
- 如果希望调用方必须显式处理(比如支付失败必须回滚+告警),继承 Exception
- 如果属于程序逻辑错误(如参数校验失败、状态非法),继承 RuntimeException 更自然
- 建议加上带 message 和 cause 的构造函数,方便封装上下文信息
在业务方法里做合法性判断后立即 throw
不要等逻辑跑完才发现问题。应在入口处或关键决策点,对业务规则做明确检查,不满足就立刻抛出——这是最典型的用法。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 例如用户下单时检查库存:
if (stock - 例如更新订单状态前校验原状态:
if (!"PAID".equals(order.getStatus())) throw new InvalidOrderStatusException("仅允许从已支付状态变更"); - 避免把多个校验堆在一行,每条规则单独判断、单独抛出,错误定位更准
包装原始异常再抛出,保留原始上下文
调用下游服务或 DAO 层出错时,不要直接把 SQLException 或 HttpClientErrorException 暴露给上层。用自定义异常包装它,既统一了错误语义,又没丢掉根源信息。
立即学习“Java免费学习笔记(深入)”;
catch (DataAccessException e) { throw new OrderPersistenceException("保存订单失败", e); }- 构造函数中传入 cause,能让日志和调试看到完整堆栈链
- 上层只需关注“订单保存失败”这个业务含义,不必了解是数据库连接超时还是唯一索引冲突
配合 @ResponseStatus 或全局异常处理器统一响应格式
在 Spring Web 项目中,抛出自定义异常后,通常不希望它变成 500 页面。可以结合注解或全局处理器,让异常自动转成标准 JSON 响应。
- 给异常类加 @ResponseStatus(HttpStatus.BAD_REQUEST),适用于简单 HTTP 状态映射
- 更推荐用 @ControllerAdvice + @ExceptionHandler,集中处理所有自定义异常,返回统一结构如
{"code": "ORDER_STOCK_SHORT", "msg": "库存不足"} - 这样前端能根据 code 做差异化提示,而不是只看 message 字符串解析

















