我正在阅读 Java 的 ArrayList 的源代码,我遇到了它的支持数组声明:
private transient Object[] elementData;
为什么这需要是暂时的?为什么这个类不能序列化?
谢谢您的帮助!
可以序列化;该类ArrayList
只是自己处理事情,而不是使用默认机制。查看该类中的writeObject()
和方法,它们是标准序列化机制的一部分。readObject()
如果您查看源代码,您会发现它writeObject()
不会保存支持数组。相反,它一次一个地序列化元素(包括空值),直到达到size()
限制。这避免了序列化数组的开销,尤其是数组末尾的任何未使用的插槽。在反序列化时,由readObject()
.
为什么这需要是暂时的?
它这样做是因为它提供了比默认值更好的序列化工作的自定义readObject
和方法。writeObject
具体来说,writeObject 方法只写入元素的大小和序列。这避免了序列化私有数组对象,该对象 1) 具有自己的标头和开销,以及 2) 通常用null
s 填充。节省空间可能是显着的。
为什么这个类不能序列化?
类ArrayList
作为一个整体可以序列化1。Object[]
可以直接序列化,但他们选择将其标记为以transient
另一种方式实现序列化。
1 - 实际上,这取决于元素的运行时类型。例如,如果您尝试序列化ArrayList
包含Thread
引用,那么您将获得第一个非空引用的运行时异常。
ArrayList
implements Serializable
,所以它可以被序列化,这就是为什么私有后备数组是transient
,所以它不会与类中的其他数据一起序列化,因为所有都由ArrayList
'swriteObject
和readObject
方法处理。
因为它实现了显式序列化。请参阅 ArrayList#writeObject。
扩展上面斯蒂芬 C 的回答,我想更正他关于使用瞬态的注释,在ArrayLists
这种情况下,为了可读性。作为他回答下的评论,这可能会更好,但我还没有那种能力!
虽然标记为的字段有助于提高可读性,但由于自定义和方法分别调用's和's方法transient
,这也是必要的。这些方法将完成处理所有未标记字段(例如)的序列化的繁琐工作。readObject
writeObject
java.io.ObjectInputStream
defaultReadObject
java.io.ObjectOutputStream
defaultWriteObject
transient
size
ObjectOutputStream
有关更多详细信息,请参阅源代码: https ://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/io/ObjectOutputStream.java#L431
该变量不可序列化。
变量是多余的。
链接:http ://onjava.com/pub/a/onjava/excerpt/JavaRMI_10/index.html?page=3