ArrayList通过将elementData声明为transient并自定义writeObject/readObject方法,仅序列化size个有效元素,避免冗余null数据传输与内存浪费,提升序列化效率且不影响正常功能。

ArrayList 在序列化时默认会把整个 elementData 数组写入流,包括尚未使用的空闲槽位(即 size 之后的 null 元素)。这会造成冗余数据传输和反序列化后内存浪费。为解决这个问题,ArrayList 自定义了 writeObject 方法,只序列化实际有效元素。
为什么 elementData 不直接序列化
底层数组 elementData 被声明为 transient:
- 避免默认序列化机制将整块数组(含大量
null)一并写入 - 绕过自动序列化,交由类自身控制哪些数据真正需要持久化
- 这是优化的前提:不参与默认序列化,才有机会做精简写入
writeObject 的核心逻辑
该方法在 ObjectOutputStream 中被反射调用,执行流程如下:
- 先调用
defaultWriteObject(),序列化非 transient 成员(如size) - 再遍历
elementData[0]到elementData[size - 1],逐个写入实际元素 - 不写
size之后的任何位置,哪怕它们在内存中存在
readObject 如何保证一致性
配套的 readObject 方法负责重建对象状态:
- 先调用
defaultReadObject()恢复size - 按
size分配新数组:elementData = new Object[size] - 逐个读取
size个元素,填入新数组对应下标 - 这样重建的
elementData长度恰好等于size,无空闲槽位
实际效果与注意事项
这种设计带来的好处是明确的:
- 网络传输或文件存储体积显著减小,尤其当
size远小于容量时(如 add 5 个元素后容量为 10) - 反序列化后内存占用更紧凑,避免持有大量无用
null引用 - 不影响功能:
get()、add()等行为完全一致,用户无感知
需注意的是,自定义序列化不改变扩容逻辑或线程安全性,它仅作用于序列化/反序列化这一特定环节。










