最有效的序列化体积优化是精简数据而非增加冗余:跳过空闲容量、用id替代对象引用、压缩基础类型编码、结合transient与手动序列化关键字段。

直接跳过默认序列化中冗余字段,只保留真正需要持久化的数据,是缩小序列化体积最有效的手段。关键不在“多写”,而在“少存”——尤其对集合、缓存、临时计算结果这类字段。
只序列化有效元素,跳过空闲容量
像 ArrayList 这类动态数组,底层是 transient Object[] elementData,实际元素数(size)常远小于数组长度。默认序列化会把整个数组(包括 null 占位)全写进去,浪费大量空间。
- 在
writeObject中调用defaultWriteObject()写入size等元信息后,只遍历前size个元素逐个写出 -
readObject中先读size,再新建数组并按顺序读回对应数量的元素 - 这样避免了序列化数百个 null 引用,体积可减少 30%–70%,取决于稀疏程度
用紧凑格式替代对象引用
避免序列化完整对象图,尤其是重复或可重建的关联对象。例如用户对象里有个 Department 引用,若部门信息已全局唯一且有 ID,就不要序列化整个部门对象。
OpenJDK 24 Windows x64 官方参考实现(24+36),适合 Windows 环境进行 Java 开发、编译、运行和版本兼容性验证。
-
writeObject中只写departmentId(比如 int 或 String),不调用out.writeObject(dept) -
readObject中读出 ID 后,通过本地缓存或工厂方法重建引用,而不是反序列化原始对象 - 既减小体积,又规避跨版本类结构不一致导致的反序列化失败
压缩基础类型与字符串编码
Java 默认用 UTF-8 写字符串,但短字符串(如状态码、枚举名)用字节或整数代替更省空间;数值字段也可根据取值范围选用更小类型写入。
- 比如
status字段只有 "ACTIVE" / "INACTIVE" 两种值,writeObject中用out.writeByte(0)或1表示,而非out.writeUTF("ACTIVE") - 时间戳用
out.writeLong(timeMillis),比序列化Date对象节省至少 20 字节 - 布尔值统一用
writeBoolean,别包装成Boolean对象再序列化
主动排除 transient + 手动补必要字段
transient 能跳过字段,但有时你需要部分保留敏感字段的摘要(如密码哈希),而非完全丢弃。
- 将原始密码字段设为
transient,在writeObject中手动out.writeUTF(passwordHash) - 同时确保
defaultWriteObject()在最前面,保证其他非 transient 字段正常落盘 - 反序列化时
defaultReadObject()也必须最先调用,再读哈希值并赋给临时字段或重建逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










