Thinking about writeObject and readObject in the underlying code of ArrayList

Without further ado, let’s start with the underlying code:

 /**
     * 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();
            }
        }

    }

Regarding the reason why elementData[] is declared unserializable:

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

When creating an ArrayList object, the default is to open up an object array with a length of 10. If only a few objects are stored (less than the default 10), if the default serialization is adopted, the remaining nulls will also be serialized to in the file.

If it is declared as a transient type, the virtual machine will not process our array by itself, which is why the write/readObject method of ArrayList is available. This way you avoid wasting resources to store data you don't have.


Also note that s.defaultWriteObject(); this step is to serialize other data in the ArrayList except transient, and then s.writeInt(size); is to serialize the size of the array first, and then put the value in the array The elements are serialized one by one. As for s.readInt();  // ignored When deserializing, I don't think this step is necessary. Look at his comment: ignore it. . . .

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324803262&siteId=291194637