Java's ArrayList uses custom serialization and explicitly writes the size. Nevertheless, size is not marked in ArrayList as transient. Why is size written two times: once via defaultWriteObject and again vis writeInt(size) as shown below (writeObject method)?
s.defaultWriteObject();
// Write out size as capacity for behavioral 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]);
}
TL;DR
It exists solely for compatibility with old java versions.
details
If you take a look at the comment above
s.writeInt(size), you can see that this is supposed to be the capacity. In previous java versions, the serialized form ofArrayListhad a size and a capacity.Both of them represent actual properties of an
ArrayList. Thesizerepresents the number of items in theArrayListwhile thecapacityrefers to the number of of possible items (length of the array) in it without the array needing to be recreated.If you take a look at
readObject, you can see that the capacity is ignored:This is because it was used in previous java versions and it still needs to be written/read to preserve compatibility.
If you look at the matching JDK6 sources, you can see that this was in fact used previously. If you have a serialized JDK6
ArrayListand try to deserialize it with a newer JDK, it will work. But if the capacity was just skipped, this would fail and you couldn't deserialize anything with anArrayListfrom that old version.