1、transient 关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被 transient 关键字修饰的。
2、被 transient 关键字修饰的变量不再能被序列化,一个静态变量不管是否被 transient 修饰,均不能被序列化。
3、一旦变量被 transient 修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。也可以认为在将持久化的对象反序列化后,被 transient 修饰的变量将按照普通类成员变量一样被初始化。
**序列化有 2 种方式:
A、只是实现了 Serializable 接口。
序列化时,调用 java.io.ObjectOutputStream 的 defaultWriteObject 方法,将对象序列化。
注意:此时 transient 修饰的字段,不会被序列化。
B、实现了 Serializable 接口,同时提供了 writeObject 方法。
序列化时,会调用该类的 writeObject 方法。而不是 java.io.ObjectOutputStream 的 defaultWriteObject 方法。 **
ArrayList 源码:
- private transient Object[] elementData;
为什么要将 elementData 修饰为 transient 呢?
比较靠谱的说法:
elementData 数组相当于容器,当容器不足时就会再扩充容量,但是容器的容量往往都是大于或者等于 ArrayList 所存元素的个数。
比如,现在实际有了 8 个元素,那么 elementData 数组的容量可能是 8x1.5=12,如果直接序列化 elementData 数组,那么就会浪费 4 个元素的空间,特别是当元素个数非常多时,这种浪费是非常不合算的。所以 ArrayList 的设计者将 elementData 设计为 transient,然后在 writeObject 方法中手动将其序列化,并且只序列化了实际存储的那些元素,而不是整个数组。
ArrayList 覆写的 writeObject()方法代码:
- private void writeObject(java.io.ObjectOutputStream s)
-
throws java.io.IOException{
-
// Write out element count, and any hidden stuff
-
int expectedModCount = modCount;
-
s.defaultWriteObject();
-
// Write out array length
-
s.writeInt(elementData.length);
-
// Write out all elements in the proper order.
-
for (int i=0; i
-
s.writeObject(elementData[i]);
-
if (modCount != expectedModCount) {
-
throw new ConcurrentModificationException();
-
}
-
}
可观察到循环时是使用 i< size 而不是 i< elementData.length 说明序列化时,只需实际存储的那些元素,而不是整个数组。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于