为什么ArrayList使用瞬态存储?

时间:2012-03-24 00:41:04

标签: java arraylist transient

我正在阅读Java的ArrayList的源代码,我遇到了它的支持数组声明:

private transient Object[] elementData;

为什么这需要是暂时的?为什么不能将这个类序列化?

感谢您的帮助!

6 个答案:

答案 0 :(得分:28)

可以序列化; ArrayList类只是处理事物本身,而不是使用默认机制。查看该类中的writeObject()readObject()方法,它们是标准序列化机制的一部分。

如果查看源代码,您会发现writeObject()未保存支持数组。相反,它一次一个地序列化元素(包括空值),直到size()限制。这避免了序列化阵列的开销,尤其是阵列末尾的任何未使用的槽。在反序列化时,readObject()创建了所需最小大小的新后备数组。

答案 1 :(得分:6)

  

为什么这需要是暂时的?

这样做是因为它提供了自定义readObjectwriteObject方法,这些方法比默认方法更好地进行序列化。具体来说,writeObject方法只写入元素的大小和顺序。这样可以避免序列化私有数组对象,该对象1)有自己的头和开销,2)通常用null填充。节省空间可能很重要。

  

为什么不能将这个类序列化?

ArrayList类作为一个整体可以序列化 1 Object[]可以直接序列化,但是他们选择将其标记为transient以另一种方式实现序列化。


1 - 实际上,这取决于元素的运行时类型。例如,如果您尝试序列化包含ArrayList引用的Thread,那么您将获得第一个非空引用的运行时异常。

答案 2 :(得分:3)

ArrayList实现Serializable,因此可以被序列化,这正是私有后备数组为transient的原因,因此它不与其他序列化类中的数据,因为所有数据都由ArrayList的{​​{1}}和writeObject方法处理。

答案 3 :(得分:1)

因为它实现了显式序列化。请参见ArrayList#writeObject。

答案 4 :(得分:1)

在上面斯蒂芬C的回答的基础上,我想更正他关于在ArrayLists的情况下使用瞬态以提高可读性的说明。作为他的回答下的评论,这可能更好,但是我还没有这种能力!

虽然将字段标记为transient有助于提高可读性,但由于自定义readObjectwriteObject方法调用java.io.ObjectInputStream的{​​{1 }}和defaultReadObject的{​​{1}}方法。这些方法将处理所有未标记为java.io.ObjectOutputStream(例如defaultWriteObject)的字段的序列化工作。

有关更多详细信息,请参见transient的源代码:https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/io/ObjectOutputStream.java#L431

答案 5 :(得分:0)

该变量不可序列化。

  • 如果变量不可序列化,那么序列化机制在尝试序列化变量时会抛出异常。为避免这种情况,您可以将变量声明为瞬态变量。

变量是多余的。

  • 假设实例缓存计算结果。在本地,我们可能想要 存储计算结果,以节省一些处理器时间。但 当我们通过线路发送对象时,我们可能会更担心消耗带宽 因此丢弃缓存的计算,因为我们以后总是可以重新生成它。

link:http://onjava.com/pub/a/onjava/excerpt/JavaRMI_10/index.html?page=3