transient与序列化
Posted youxin2012
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了transient与序列化相关的知识,希望对你有一定的参考价值。
transient的作用: 修饰实力域,使其从一个类的默认序列化形式中省略(即默认序列化方式不对该字段做写与读 存取操作)应用场景:
- 业务需要,不宜做序列化
- 默认的序列化方式不适合,采用自定义序列化的方式
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
那么问题来了,既然table中存储着hashMap中的元素信息,为什么不序列化?
答:不是不序列化,而是不采用默认的序列化。 由于table中元素信息是我们存取关注的,而非table的结构,所以能合理的完成table中所有信息的存取是关键。 鉴于table结构过于复杂(其中的链表结构为Entry 结点构成的链表),若采用默认的序列化方式,会将table的完整结构(包括各链表)镜像一份,如此以来带来一下弊端: 1. 不仅需要消化大量时间遍历table结构 2. 占用较多的存储空间 3. 默认序列化对对象图做递归遍历当表过大时会发生堆栈溢出,所以避免使用默认的序列化方式。 hashMap中采用序列化存储过程中遍历table中元素,并逐一序列化储存。而在序列化读取过程中,根据读出数值还原表结构的方式来完成,从而提高序列化的质量。过程如下:
private void writeObject(java.io.ObjectOutputStream s)
throws IOException
// Write out the threshold, loadfactor, and any hidden stuff
s.defaultWriteObject();
….
//自定义完成table中信息的存储
// Write out keys and values (alternating)
if (size > 0)
for(Map.Entry<K,V> e : entrySet0())
s.writeObject(e.getKey());
s.writeObject(e.getValue());
private static final long serialVersionUID = 362498820763181265L;
/**
* Reconstitute the @code HashMap instance from a stream (i.e.,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
// Read in the threshold (ignored), loadfactor, and any hidden stuff
s.defaultReadObject();
...
//依次读取,并还原表结构
// Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i < mappings; i++)
K key = (K) s.readObject();
V value = (V) s.readObject();
putForCreate(key, value);
如此,当自定义中实例域存储机构将复杂,默认序列化方式无法胜任时,可以声明为transient,并自定义完成该字段中信息的序列化。
以上是关于transient与序列化的主要内容,如果未能解决你的问题,请参考以下文章