简体   繁体   English

为什么 ArrayList 使用瞬态存储?

[英]Why does ArrayList use transient storage?

I was reading the source of Java's ArrayList and I came across its backing array declaration:我正在阅读 Java 的 ArrayList 的源代码,我遇到了它的支持数组声明:

private transient Object[] elementData;

Why does this need to be transient?为什么这需要是短暂的? Why can't this class be serialized?为什么这个类不能序列化?

Thanks for the help!谢谢您的帮助!

It can be serialized;可以序列化; the ArrayList class just takes care of things itself, rather than using the default mechanism. ArrayList类只是自己处理事情,而不是使用默认机制。 Look at the writeObject() and readObject() methods in that class, which are part of the standard serialization mechanism.查看该类中的writeObject()readObject()方法,它们是标准序列化机制的一部分。

If you look at the source, you see that writeObject() does not save the backing array.如果查看源代码,您会看到writeObject()不保存支持数组。 Instead, it serializes the elements (including null values) one at a time up to the size() limit.相反,它一次一个地序列化元素(包括空值),直至达到size()限制。 This avoids the overheads of serializing the array, and especially any unused slots at the end of the array.这避免了序列化数组的开销,尤其是数组末尾的任何未使用的插槽。 On deserialization, a new backing array of the minimum required size is created by readObject() .在反序列化时, readObject()创建一个最小所需大小的新支持数组。

Why does this need to be transient?为什么这需要是短暂的?

It does this because it provides custom readObject and writeObject methods that do a better job of serialization than the default.它这样做是因为它提供了自定义的readObjectwriteObject方法,这些方法比默认的序列化工作做得更好。 Specifically, the writeObject method writes just the size and the sequence of elements.具体来说,writeObject 方法只写入元素的大小和序列。 This avoids serializing the private array object which 1) has its own header and overheads, and 2) is typically padded with null s.这避免了序列化私有数组对象,该对象 1) 具有自己的标头和开销,并且 2) 通常用null填充。 The space saving can be significant.空间节省可能是显着的。

Why can't this class be serialized?为什么这个类不能序列化?

The ArrayList class as a whole can be serialized 1 . ArrayList类作为一个整体可以序列化1 The Object[] could be serialized directly, but they chose to mark it as transient implement the serialization another way. Object[]可以直接序列化,但他们选择将其标记为transient以另一种方式实现序列化。


1 - Actually, this depends on the elements' runtime types. 1 - 实际上,这取决于元素的运行时类型。 For example, if you attempted to serialize an ArrayList containing Thread references, then you would get a runtime exception for the first non-null reference.例如,如果您尝试序列化包含Thread引用的ArrayList ,那么您将收到第一个非空引用的运行时异常。

ArrayList实现了Serializable ,因此它可以被序列化,这正是私有后备数组是transient ,因此它不会与类中的其他数据一起序列化,因为所有这些都是由ArrayListwriteObjectreadObject方法处理的。

Because it implements explicit serialization.因为它实现了显式序列化。 See ArrayList#writeObject.请参见 ArrayList#writeObject。

Extending on Stephen C's answer above, I would like to correct his note about transient being used, in ArrayLists 's case, for readability.扩展上面斯蒂芬 C 的回答,我想更正他关于在ArrayLists的情况下使用瞬态的注释,以提高可读性。 This may be better as a comment under his answer but I don't have that ability yet!在他的回答下作为评论可能会更好,但我还没有那种能力!

While the field being marked as transient is helpful for readability, it is also necessary due to the custom readObject and writeObject methods calling java.io.ObjectInputStream 's defaultReadObject and java.io.ObjectOutputStream 's defaultWriteObject methods respectively.虽然将字段标记为transient有助于提高可读性,但由于自定义readObjectwriteObject方法分别调用java.io.ObjectInputStreamdefaultReadObjectjava.io.ObjectOutputStreamdefaultWriteObject方法,这也是必要的。 These methods will do the dirty work of handling serializiation of all the fields not marked transient (eg size ).这些方法将完成处理所有未标记为transient (例如size )的字段的序列化的肮脏工作。

See the source code for ObjectOutputStream for more details here: https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/io/ObjectOutputStream.java#L431有关更多详细信息,请参阅ObjectOutputStream的源代码: https : //github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/io/ObjectOutputStream.java#L431

The variable isn't serializable.该变量不可序列化。

  • If the variable isn't serializable, then the serialization mechanism will throw an exception when it tries to serialize the variable.如果变量不可序列化,那么序列化机制将在尝试序列化变量时抛出异常。 To avoid this, you can declare the variable to be transient.为避免这种情况,您可以将变量声明为瞬态。

The variable is redundant.变量是多余的。

  • Suppose that the instance caches the result of a computation.假设实例缓存了计算结果。 Locally, we might want to store the result of the computation, in order to save some processor time.在本地,我们可能希望存储计算结果,以节省一些处理器时间。 But when we send the object over the wire, we might worry more about consuming bandwidth and thus discard the cached computation since we can always regenerate it later on.但是当我们通过网络发送对象时,我们可能会更担心消耗带宽,从而丢弃缓存的计算,因为我们以后总是可以重新生成它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM