ArrayList底层代码中的writeObject和readObject问题思考

废话不多说,先上底层代码:

 /**
     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     * is, serialize it).
     *
     * @serialData The length of the array backing the <tt>ArrayList</tt>
     *             instance is emitted (int), followed by all of its elements
     *             (each an <tt>Object</tt>) in the proper order.
     */
    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();
        }
    }


    /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    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();
            }
        }

    }

关于elementData【】被声明为不可序列化的原因:

    * private static final long serialVersionUID = 8683452581122892189L;  
    * private transient Object elementData[];  
    * private int size; 

在new一个ArrayList对象时,默认是开辟一个长度为10的对象数组,如果只存入几个对象(不到默认的10个),如果采用默认序列化,则会将其余为null也序列化到文件中。


如果声明为transient类型,就能让虚拟机不会自行处理我们的这个数组,这才有了ArrayList的write/readObject方法。通过这种方式避免了浪费资源去存储没有的数据。

 

还要注意的是s.defaultWriteObject();这一步是将ArrayList中除了transient的其他数据序列化,而后s.writeInt(size);则是把先把数组大小序列化,然后再把数组中有值的元素一一序列化。至于s.readInt(); // ignored反序列化的时候我觉得其实这一步没什么必要,你看他的注释:忽略的意思嘛。。。。
---------------------
作者:liuyancainiao
来源:CSDN
原文:https://blog.csdn.net/liuyancainiao/article/details/80051353
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2018-12-31 20:55  如果可以在重来  阅读(743)  评论(0)    收藏  举报