Java's transient keyword

In the study of java collection classes , we found that ArrayList class and Vector class are both implemented using arrays, but there is a slight difference in defining the attribute of array elementData, that is, ArrayList uses the transient keyword


private transient Object[] elementData;

protected Object[] elementData;

So, first, let's take a look at what the transient keyword does.

transient

       Java language keywords, variable modifiers, if you declare an instance variable with transient, its value does not need to be maintained when the object is stored. The object storage here refers to a mechanism provided by Java's serialization to persist object instances. When an object is serialized, the values ​​of transient variables are not included in the serialized representation, whereas non-transient variables are included. The use case is: when persisting an object, there may be a special object data member, and we don't want to use serialization mechanism to save it. To turn off serialization on a field of a particular object, the keyword transient can be prefixed to the field.

ArrayList uses the transient keyword for storage optimization, while Vector does not. Why?

ArrayList

/**
     * 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 array length
        s.writeInt(elementData.length);

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

    }

ArrayList implements the writeObject method, and you can see that only the data at the non-null array position is saved. That is, the elementData of the size of the list. An additional point to note is that the implementation of ArrayList provides a fast-fail mechanism that provides weak consistency.

Vector

/**
     * Save the state of the {@code Vector} instance to a stream (that
     * is, serialize it).
     * This method performs synchronization to ensure the consistency
     * of the serialized data.
     */
    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
        final java.io.ObjectOutputStream.PutField fields = s.putFields();
        final Object[] data;
        synchronized (this) {
            fields.put("capacityIncrement", capacityIncrement);
            fields.put("elementCount", elementCount);
            data = elementData.clone();
        }
        fields.put("elementData", data);
        s.writeFields();
    }

Vector also implements the writeObject method, but the method does not optimize storage like ArrayList. When the implementation statement is
data = elementData.clone();
clone(), the null value will also be copied. Therefore, Vector and ArrayList that store the same content, Vector occupies more bytes than ArrayList.

You can test, serialize the Vector and ArrayList that store the same content into a text file respectively. *Vector needs 243 bytes * ArrayList needs 135 bytes

ArrayList is an asynchronous implementation of a single-threaded more efficient data structure (compared to Vector).
ArrayList only provides weak consistency through a modified record field, mainly used in iterators. There is no synchronized method. That is, the Fast-fail mechanism mentioned above. The storage structure of ArrayList is defined as transient, and writeObject is rewritten to implement custom serialization and optimize storage.

Vector is a more reliable data structure in a multithreaded environment, and all methods are synchronized.

  • Synchronous processing: Vector synchronization, ArrayList asynchronous
  • By default, Vector doubles the length of the array, and ArrayList doubles it by 0.5.

ArrayList: int newCapacity = oldCapacity + (oldCapacity >> 1);

ArrayList automatically expands the capacity to 1.5 times the original capacity (when implemented, the method will pass in an expected minimum capacity. If the capacity is still less than the minimum capacity after expansion, then the capacity will be the incoming minimum capacity. Arrays used when expanding. The copyOf method finally calls the native method for new array creation and data copy)

Vector: int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);

When Vector specifies initialCapacity and capacityIncrement to initialize, each time the capacityIncrement is increased


Guess you like

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