Java自定义序列化通过重写private writeObject/readObject方法实现,可控制字段参与、编码方式及校验;配合transient跳过默认序列化,并需显式声明serialVersionUID保障版本兼容。

Java 中自定义序列化过程,核心是绕过默认的字段全量序列化机制,由开发者主动控制哪些字段参与、如何编码、是否做预处理或校验。这主要通过重写 writeObject 和 readObject 方法实现,而不是靠外部工具或框架。
实现 writeObject 控制序列化行为
在实现了 Serializable 的类中,添加私有方法 private void writeObject(ObjectOutputStream out) throws IOException。JVM 会自动调用它替代默认逻辑:
- 必须先调用
out.defaultWriteObject()(如果还想保留部分默认行为) - 可以手动写入额外字段,比如计算出的哈希值、时间戳或加密后的敏感数据
- 可跳过某些字段:不调用
defaultWriteObject(),完全自己用out.writeUTF()、out.writeInt()等逐个写入 - 适合做运行时校验,例如序列化前检查对象状态是否合法,不合法则抛
IOException
实现 readObject 恢复对象状态
对应地,定义 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException:
- 若之前调用了
defaultWriteObject(),这里也应先调用in.defaultReadObject() - 按写入顺序反向读取:比如
writeUTF对应readUTF,writeInt对应readInt - 可用于重建瞬态资源,如重新初始化
transient字段(例如连接池、缓存 Map) - 支持版本兼容:读取时判断流中是否有新字段,没有就设默认值
用 transient 配合自定义逻辑跳过字段
transient 关键字本身不构成“自定义”,但它是自定义序列化的基础配合项:
立即学习“Java免费学习笔记(深入)”;
- 标记不想被默认序列化的字段(如密码、线程、IO 流等)
- 在
writeObject中可选择性地加密后写入,或只写摘要 - 在
readObject中根据上下文重新生成或恢复该字段 - 注意:static 字段天然不参与序列化,无需加
transient
serialVersionUID 的作用不能忽略
显式声明 private static final long serialVersionUID = 1L; 是良好实践:
- 避免 JVM 自动生成导致类结构微调后反序列化失败
- 升级类时,若字段语义不变(如仅增加 getter),可保持 ID 不变
- 若字段删除或类型变更,应修改 ID,让反序列化直接报
InvalidClassException,而非静默出错


















