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