java业务异常类需继承runtimeexception并重载全部四个标准构造方法,每个都必须调用super(message)或super(message, cause)以保留异常链,同时可添加code、data等业务字段及静态工厂方法,但不可重写getcause()或在getmessage()中拼接cause。

Java中统一业务异常包装类要保留异常链,关键在于所有构造方法都必须调用 super(cause) 或显式传递 cause 给父类,且不能用 new RuntimeException(msg) 这类丢弃 cause 的写法。
继承 RuntimeException 并重载全部标准构造方法
业务异常通常为非检查异常,应继承 RuntimeException。为确保异常链不丢失,需覆盖全部四个标准构造方法(无参、String、Throwable、String+Throwable),每个都正确委托给父类:
-
无参构造:可设默认业务码和消息,但内部仍调用
super() -
仅传 message:调用
super(message),不丢弃潜在 cause(此时 cause 为 null,合法) -
仅传 cause:必须调用
super(cause),这是保留原始异常栈的核心 -
同时传 message 和 cause:调用
super(message, cause),既带业务语义又完整保留原始异常链
添加业务字段(如 code、data)但不干扰异常链
可在类中定义 private final int code、private final Object data 等字段,并在所有构造方法中初始化。注意:这些字段只用于业务上下文携带,不可用于替代 Throwable 的 cause 机制。例如:
- 不要在
getMessage()中拼接 cause 的信息——这会掩盖原始异常描述 - 不要重写
getCause()方法——应直接继承父类行为,保证 JDK 异常处理逻辑(如ExceptionUtils.getRootCause())仍能正常工作 - 若需扩展异常信息,建议提供
getBusinessCode()、getExtraData()等独立 getter 方法
提供静态便捷构造方法,内部仍保障 cause 传递
为提升可读性,可添加如 of(int code, String msg)、withCause(int code, String msg, Throwable cause) 等静态工厂方法。重点是:这些方法在内部创建实例时,仍必须调用对应含 cause 的构造器。例如:
-
of(1001, "库存不足")→ 调用new BizException(1001, "库存不足")(无 cause,安全) -
withCause(1002, "支付失败", e)→ 调用new BizException(1002, "支付失败", e)(显式传 cause,链完整) - 避免写成
new BizException(1002, "支付失败").initCause(e)——initCause()有调用限制(只能设一次、不能重复设),且易出错
配合全局异常处理器验证链完整性
在 Spring MVC 或 WebFlux 中,使用 @ControllerAdvice 捕获该异常时,可通过 ex.getCause() 或遍历 Throwable#getSuppressed()(如有)确认原始异常未丢失。日志打印建议用 SLF4J 的 logger.error("业务异常", ex) 形式——它会自动输出完整栈,包括 cause 链。
不复杂但容易忽略:只要每个构造路径都经过 super(...) 且未手动清空 cause,JVM 就会维护完整的异常传播路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











