ArrayList的序列化是怎么实现的?

1 个回答

  • 徐霖
    理解一切,没有对错,让花成花,让树成树。
    在 `ArrayList` 的序列化实现中,通过自定义的 `writeObject` 和 `readObject` 方法控制了序列化和反序列化过程。这种自定义序列化实现避免了 `ArrayList` 底层数组 `elementData` 在默认序列化过程中带来的空间浪费。以下是具体的实现和原因。 ### 1. 序列化实现概述 `ArrayList` 序列化的关键在于它自定义了 `writeObject` 和 `readObject` 方法。在 Java 中,当类实现了 `Serializable` 接口后: - 如果定义了 `writeObject` 和 `readObject` 方法,序列化和反序列化会优先调用这些方法。 - 否则会使用 `ObjectOutputStream` 和 `ObjectInputStream` 的 `defaultWriteObject` 和 `defaultReadObject` 方法,进行默认序列化和反序列化。 `ArrayList` 重写了这两个方法,直接控制序列化数据,确保仅序列化有效元素,而非整个数组容量。 ### 2. `ArrayList` 中 `elementData` 的 `transient` 关键字 `ArrayList` 的底层数据存储是一个 `Object[]` 数组,命名为 `elementData`,并被声明为 `transient`。这样做的原因是: - `elementData` 数组容量通常大于实际元素数,默认序列化会序列化整个数组,导致大量 `null` 元素被序列化,浪费空间。 - 将 `elementData` 声明为 `transient` 可以避免默认序列化,从而仅在 `writeObject` 和 `readObject` 中序列化有效元素。 ### 3. `writeObject` 和 `readObject` 的实现 #### `writeObject` 方法 在 `writeObject` 方法中,`ArrayList` 仅序列化实际包含的元素,并避免了无效的 `null` 元素。 ```java private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { int expectedModCount = modCount; s.defaultWriteObject(); // 序列化非 transient 字段(如 size) s.writeInt(size); // 序列化实际元素数量 // 序列化有效的元素 for (int i = 0; i < size; i++) { s.writeObject(elementData[i]); } // 防止并发修改 if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } ``` #### `readObject` 方法 `readObject` 方法在反序列化时将数据读入 `ArrayList` 的 `elementData` 中。步骤如下: 1. 调用 `defaultReadObject` 读取非 `transient` 字段(如 `size`)。 2. 根据实际 `size` 分配 `elementData` 数组空间。 3. 将所有序列化的有效元素依次读入 `elementData`。 ```java private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; s.defaultReadObject(); // 反序列化非 transient 字段 s.readInt(); // 忽略的容量 if (size > 0) { ensureCapacityInternal(size); // 确保数组容量 Object[] a = elementData; for (int i = 0; i < size; i++) { a[i] = s.readObject(); // 读取每个实际元素 } } } ``` ### 4. 总结 - `ArrayList` 通过将 `elementData` 声明为 `transient`,避免了默认序列化的空间浪费。 - `writeObject` 和 `readObject` 方法通过手动控制序列化,仅序列化有效元素,保证了序列化的效率。 - 在序列化期间,`ArrayList` 的 `size` 和 `modCount` 也被记录和校验,以确保数据一致性和安全性。
    发布于 2024-11-10 13:53 •IP属地 黑龙江
    举报
    评论
    收藏