关键词搜索

源码搜索 ×
×

Java的transient关键字

发布2015-01-09浏览2046次

详情内容

在关于 java的集合类的学习中,我们发现ArrayList类和Vector类都是使用数组实现的,但是在定义数组elementData这个属性时稍有不同,那就是ArrayList使用transient关键字


  1. private transient Object[] elementData;
  2. protected Object[] elementData;

那么,首先我们来看一下transient关键字的作用是什么。

transient

       Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。这里的对象存储是指,Java的serialization提供的一种持久化对象实例的机制。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。使用情况是:当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。

ArrayList使用了transient关键字进行存储优化,而Vector没有这样做,为什么?

ArrayList

  1. /**
  2. * Save the state of the <tt>ArrayList</tt> instance to a stream (that
  3. * is, serialize it).
  4. *
  5. * @serialData The length of the array backing the <tt>ArrayList</tt>
  6. * instance is emitted (int), followed by all of its elements
  7. * (each an <tt>Object</tt>) in the proper order.
  8. */
  9. private void writeObject(java.io.ObjectOutputStream s)
  10. throws java.io.IOException{
  11. // Write out element count, and any hidden stuff
  12. int expectedModCount = modCount;
  13. s.defaultWriteObject();
  14. // Write out array length
  15. s.writeInt(elementData.length);
  16. // Write out all elements in the proper order.
  17. for (int i=0; i<size; i++)
  18. s.writeObject(elementData[i]);
  19. if (modCount != expectedModCount) {
  20. throw new ConcurrentModificationException();
  21. }
  22. }

ArrayList实现了writeObject方法,可以看到只保存了非null的数组位置上的数据。即list的size个数的elementData。需要额外注意的一点是,ArrayList的实现,提供了fast-fail机制,可以提供弱一致性。

Vector

  1. /**
  2. * Save the state of the {@code Vector} instance to a stream (that
  3. * is, serialize it).
  4. * This method performs synchronization to ensure the consistency
  5. * of the serialized data.
  6. */
  7. private void writeObject(java.io.ObjectOutputStream s)
  8. throws java.io.IOException {
  9. final java.io.ObjectOutputStream.PutField fields = s.putFields();
  10. final Object[] data;
  11. synchronized (this) {
  12. fields.put("capacityIncrement", capacityIncrement);
  13. fields.put("elementCount", elementCount);
  14. data = elementData.clone();
  15. }
  16. fields.put("elementData", data);
  17. s.writeFields();
  18. }

Vector也实现了writeObject方法,但方法并没有像ArrayList一样进行优化存储,实现语句是
data = elementData.clone();
clone()的时候会把null值也拷贝。所以保存相同内容的Vector与ArrayList,Vector的占用的字节比ArrayList要多。

可以测试一下,序列化存储相同内容的Vector与ArrayList,分别到一个文本文件中去。* Vector需要243字节* ArrayList需要135字节

ArrayList是非同步实现的一个单线程下较为高效的数据结构(相比Vector来说)。
ArrayList只通过一个修改记录字段提供弱一致性,主要用在迭代器里。没有同步方法。 即上面提到的Fast-fail机制.ArrayList的存储结构定义为transient,重写writeObject来实现自定义的序列化,优化了存储。

Vector是多线程环境下更为可靠的数据结构,所有方法都实现了同步。

  • 同步处理:Vector同步,ArrayList非同步
  • Vector缺省情况下增长原来一倍的数组长度,ArrayList是0.5倍.

ArrayList: int newCapacity = oldCapacity + (oldCapacity >> 1);

ArrayList自动扩大容量为原来的1.5倍(实现的时候,方法会传入一个期望的最小容量,若扩容后容量仍然小于最小容量,那么容量就为传入的最小容量。扩容的时候使用的Arrays.copyOf方法最终调用native方法进行新数组创建和数据拷贝)

Vector: int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);

Vector指定了initialCapacity,capacityIncrement来初始化的时候,每次增长capacityIncrement


相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载