java自定义异常类需实现serializable并固定serialversionuid,业务字段不可用transient且类型须可序列化,反序列化时须校验字段合法性,jackson反序列化需提供无参构造或@jsoncreator。

Java 自定义异常类要让属性(如 code、msg、traceId、context)在序列化与反序列化后不丢失、不错乱,关键不是“能不能序列化”,而是“字段是否完整保留、类型是否合法、语义是否一致”。下面分几个重点讲清楚。
必须实现 Serializable 并固定 serialVersionUID
自定义异常类不能只靠继承 RuntimeException 就认为可序列化——因为 RuntimeException 本身没实现 Serializable。你得显式实现接口,并声明一个固定的 serialVersionUID:
- 加
implements Serializable - 写
private static final long serialVersionUID = 1L;(建议用 IDE 自动生成,避免手误) - 一旦类结构变动(比如删字段、改
final为非final),serialVersionUID不匹配就会直接抛InvalidClassException
业务字段不能是 transient,且类型必须可序列化
错误码、消息、上下文这些核心字段,必须确保能被正常写入和还原:
-
private final int code;和private final String msg;可以保留final,但不能加transient -
private String traceId;、private Map<string object> context;</string>这类字段,类型本身也要可序列化(例如HashMap可以,ThreadLocal或Connection就不行) - 如果字段类型不可序列化,要么换类型(如用
String存 JSON),要么加transient并配合自定义序列化逻辑手动处理
反序列化时需校验字段合法性
Java 反序列化会绕过构造方法,直接设字段值。这意味着非法状态可能被构造出来:
- 比如
code被设成负数、msg为空字符串,但业务上不允许 - 应在
private void readObject(ObjectInputStream in)中做检查,发现非法就抛InvalidObjectException - 同时记得先调用
in.defaultReadObject(),再做校验和补充逻辑
Jackson JSON 反序列化要解决无参构造问题
如果用 Jackson 把 JSON 转成异常对象(比如调试或 Mock 场景),常报 Missing default constructor:
- 最简单:加一个
public MyException() {}(注意 final 字段需允许为空或提供默认值) - 更可控:用
@JsonCreator标记带参构造,并给每个参数加@JsonProperty - 更推荐:别直接反序列化异常类,而是定义专用的
ErrorResponseDTO,由全局异常处理器统一转换
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











