Why Does Java’s ArrayList Use transient? Uncover the Custom Serialization Secrets

This article explains how Java’s ArrayList uses the transient keyword during serialization to skip the underlying array, reducing redundant data, and details the custom writeObject and readObject methods that ensure only actual elements are stored and restored efficiently.

Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Why Does Java’s ArrayList Use transient? Uncover the Custom Serialization Secrets

In Java, the ArrayList serialization process marks the underlying array with transient to avoid the default serialization of the entire array, thereby reducing redundant data and improving performance while ensuring correct storage and recovery through custom logic.

Avoid Unnecessary Serialization, Save Space

The underlying array of an ArrayList is often larger than the number of stored elements because its capacity exceeds its current size. Serializing the whole array would also serialize this empty space, wasting storage (e.g., 20 elements with capacity 50 would serialize 30 unused slots). By marking the array as transient, Java’s default serialization skips it, and the custom ArrayList logic serializes only the actual elements.

ArrayList's Custom Serialization Method

ArrayList

implements writeObject and readObject to define its own serialization and deserialization behavior.

Serialization Logic

Only the effective elements are serialized, not the entire backing array:

private void writeObject(ObjectOutputStream s) throws IOException {
    // Serialize non‑array fields
    s.defaultWriteObject();

    // Serialize the number of actual elements
    s.writeInt(size);

    // Serialize each valid element
    for (int i = 0; i < size; i++) {
        s.writeObject(elementData[i]);
    }

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

Deserialization Logic

The custom readObject method reconstructs the ArrayList from the object stream:

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
    // Initialize the backing array as empty
    elementData = EMPTY_ELEMENTDATA;

    // Read non‑transient fields using default mechanism
    s.defaultReadObject();

    // The capacity read here is ignored; only the actual size matters
    s.readInt(); // ignored

    if (size > 0) {
        int capacity = calculateCapacity(elementData, size);
        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
        ensureCapacityInternal(size);
        Object[] a = elementData;
        for (int i = 0; i < size; i++) {
            a[i] = s.readObject();
        }
    }
}

Summary

Avoid Redundant Data : By serializing only effective elements, storage space is saved and serialization efficiency is improved.

Flexibility : Custom serialization logic allows ArrayList to control how the underlying array is rebuilt.

Performance Optimization : Skipping the full array copy reduces processing overhead during serialization.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaserializationArrayListcustom serializationtransient
Xuanwu Backend Tech Stack
Written by

Xuanwu Backend Tech Stack

Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.