为什么 ArrayList 大小字段不是瞬态的?

Why is the ArrayList size field not transient?

Java 的 ArrayList 使用自定义序列化并显式写入 size。然而,ArrayList 中未将大小标记为 transient。为什么大小写了两次:一次通过 defaultWriteObject 一次通过 writeInt(size) 如下所示(writeObject 方法)?

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

它的存在只是为了与旧 java 版本兼容。

详情

如果你看一下上面的评论 s.writeInt(size),你会发现这应该是容量。在以前的 java 版本中,ArrayList 的序列化形式具有大小和容量。

两者都代表ArrayList的实际属性。 size 表示 ArrayList 中的项目数,而 capacity 表示其中可能的项目数(数组长度),无需重新创建数组。

如果你看一下readObject,你会发现容量被忽略了:

// Read in capacity
s.readInt(); // ignored

这是因为它在以前的 java 版本中使用,并且仍然需要 written/read 以保持兼容性。

如果你查看the matching JDK6 sources,你会发现这实际上是以前使用过的。如果你有一个序列化的 JDK6 ArrayList 并尝试用更新的 JDK 反序列化它,它会起作用。但是,如果刚刚跳过容量,这将失败,并且您无法使用旧版本的 ArrayList 反序列化任何内容。