Java自定义业务异常应继承RuntimeException,命名需体现业务语义(如InsufficientBalanceException),保留关键字段、提供常用构造方法,由全局处理器统一响应并支持错误码与国际化。

Java 自定义业务异常类,核心是继承 RuntimeException(非检查异常),命名要体现业务语义,避免泛化(如 XxxException),优先用 XxxBusinessException 或 XxxException(在明确属于业务域前提下)。
命名规范:清晰表达业务意图
业务异常不是技术错误,而是业务规则被违反时的主动抛出。命名应让人一眼看懂“什么业务场景出了问题”:
-
推荐:
InsufficientBalanceException、OrderAlreadyShippedException、InvalidPromotionCodeException -
慎用:
BusinessException(太宽泛,无法定位场景)、MyException(无意义) -
可选后缀:统一加
Exception即可,无需再加Business;若项目已有通用BusinessException基类,子类可直接叫InventoryShortageException,语义已足够明确
编写要点:轻量、实用、可扩展
不需要重写所有构造方法,聚焦常用场景即可。一个典型的自定义业务异常类示例如下:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
public class InsufficientBalanceException extends RuntimeException {
private final String accountId;
public InsufficientBalanceException(String accountId) {
super("账户 " + accountId + " 余额不足");
this.accountId = accountId;
}
public InsufficientBalanceException(String accountId, String message) {
super(message);
this.accountId = accountId;
}
// 可选:提供 errorCode 用于统一错误码管理
public String getErrorCode() {
return "BALANCE_INSUFFICIENT";
}
public String getAccountId() {
return accountId;
}
}
- 继承
RuntimeException:业务异常通常不强制上层捕获,符合“业务失败 ≠ 系统故障”的设计原则 - 保留必要字段(如
accountId):便于日志记录、监控告警或返回前端上下文信息 - 提供含参构造:至少覆盖「带业务ID的默认提示」和「自定义消息」两种常见抛出方式
- 避免重写
fillInStackTrace():除非有极致性能要求,否则会丢失关键堆栈信息
使用建议:在哪抛、怎么抛、怎么接
业务异常应在服务层(Service)中,在明确校验失败后立即抛出,不要包装成其他异常:
立即学习“Java免费学习笔记(深入)”;
-
正确:
if (balance -
避免:
throw new RuntimeException("余额不足")(丢失类型信息)、throw new IllegalArgumentException(...)(语义错位) - 全局异常处理器(如
@ControllerAdvice)统一捕获这些异常,转为标准响应(如{ "code": "BALANCE_INSUFFICIENT", "message": "账户 XXX 余额不足" }) - 日志中建议打印异常实例(而不仅是 message),方便通过类型快速筛选问题
进阶考虑:是否需要错误码与国际化
中大型项目建议为每个业务异常分配唯一错误码(String 或枚举),并配合 i18n 消息源动态生成提示:
- 错误码用于前端判断行为(如跳转、重试、禁用按钮),比字符串匹配更可靠
- 可将错误码定义为枚举:
BALANCE_INSUFFICIENT("BALANCE_INSUFFICIENT", "余额不足"),异常类持有一个枚举实例 - 不强求在异常类中内置多语言逻辑,由外部
MessageSource统一处理更灵活

















