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.
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
ArrayListimplements 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Xuanwu Backend Tech Stack
Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
