该定义自定义异常有必要——当需差异化处理错误、返回结构化错误信息、准确表达业务语义或统一日志监控时,自定义异常能提升可识别性、可维护性与协作效率。

业务代码中该不该自定义异常,不取决于“能不能”,而在于“有没有必要”——核心是看它能否让错误更可识别、更易处理、更利于协作。
当错误需要被差异化处理时
如果不同业务失败场景要求下游做出不同响应,仅靠 message 字符串判断不可靠,必须靠类型区分:
- 用户余额不足 → 触发充值提醒短信
- 订单已取消 → 自动重试下单流程
- 优惠券过期 → 返回特定错误码 40001 并引导领新券
这时用 InsufficientBalanceException、OrderCancelledException、CouponExpiredException 等具体类型,比统一 throw RuntimeException("余额不足") 更安全、更可维护。
当接口需返回结构化错误信息时
HTTP 接口面向前端或第三方系统,错误响应通常包含 code、message、details。自定义异常可天然携带这些字段:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 在异常类中定义
private final int errorCode和private final String requestId - 全局异常处理器(如
@ControllerAdvice)根据异常类型提取字段,组装标准 JSON 响应 - 避免在 service 层拼接字符串、在 controller 层 if-else 判断 message 内容
当内置异常无法准确表达业务语义时
IllegalArgumentException 或 IllegalStateException 虽通用,但丢失业务上下文:
- 抛
IllegalArgumentException("status must be PENDING")不如抛InvalidOrderStatusTransitionException("从 PAID 到 PENDING 不合法") - 前者只说明参数错,后者明确指出状态流转规则被违反,对排查和文档都更友好
- 团队成员读到异常名,立刻理解问题本质,无需翻源码查校验逻辑
当需要统一日志、监控或告警维度时
运维和 SRE 关注的是“哪类业务错误高频发生”。自定义异常类名就是天然的指标标签:
- 监控平台按异常全限定名聚合:统计
InventoryShortageException每分钟出现次数 - 日志系统自动为
*Exception添加 traceId、业务单号等 MDC 字段 - 告警规则可配置“连续 5 次出现
PaymentTimeoutException”触发通知

















