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

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

典型回答

在ArrayList的内部实现中,用于存储元素的数组(**transient Object[] elementData;**)被声明为transient,这意味着默认的序列化机制不会序列化这个数组。

那么,ArrayList是如何实现序列化的呢?

**ArrayList自定义了序列化过程,通过重写writeObject和readObject方法。 **

之所以这么做,ArrayList的数组通常会有一些空的位置(因为容量会预留一些空间),为了节省空间和提高效率,ArrayList没有使用默认的序列化机制,而是自定义了序列化,只序列化实际存储的元素,而不是整个数组。

ArrayList重写了writeObject和readObject方法,如下所示:

private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    elementData = EMPTY_ELEMENTDATA;

    // Read in size, and any hidden stuff
    s.defaultReadObject();

    // Read in capacity
    s.readInt(); // ignored

    if (size > 0) {
        // be like clone(), allocate array based upon size not capacity
        ensureCapacityInternal(size);

        Object[] a = elementData;
        // Read in all elements in the proper order.
        for (int i=0; i<size; i++) {
            a[i] = s.readObject();
        }
    }
}
private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException{
    // Write out element count, and any hidden stuff
    int expectedModCount = modCount;
    s.defaultWriteObject();

    // Write out size as capacity for behavioural compatibility with clone()
    s.writeInt(size);

    // Write out all elements in the proper order.
    for (int i=0; i<size; i++) {
        s.writeObject(elementData[i]);
    }

    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

知识扩展

为什么底层数组要使用transient

ArrayList实际上是动态数组,每次在放满以后自动增长设定的长度值,如果数组自动增长长度设为100,而实际只放了一个元素,那就会序列化99个null元素。为了保证在序列化的时候不会将这么多null同时进行序列化,ArrayList把元素数组设置为transient。

所以,为了避免Java自带的序列化机制造成的空间浪费,把数组定义为transient,然后重写writeObject和readObject来实现序列化操作。