一. 首先贴一篇解释transient关键字的文章
What is transient keyword in Java?
What is Serialization?
If you want to understand what is transient, please learn about what is Serilization concept in Java if you are not familiar with that. Serialization is the process of making the object’s state is persistent. That means the state of the object is converted into stream of bytes and stored in a file. In the same way we can use the de-serilization concept to bring back the object’s state from bytes. This is one of the important concept in Java programming because this serialization is mostly used in the networking programming. The object’s which are needs to be transmitted through network has to be converted as bytes, for that purpose every class or interface must implement serialization interface. It is a marker interface without any methods.
理解:首先需要了解一下什么事序列化,序列化就是将对象的状态进行持久化,它将对象的状态转换为字节流存储到一个文件当中,通过反序列化将字节文件重新转换为对象。序列化与反序列化主要用在网络变成当中。需要进行网络传输的对象都需要转换为字节文件,通过实现序列化接口来达到目的。序列化接口就是一个标记接口,他没有任何的方法。
What is Transient?
The keyword transient in Java used to indicate that the variable should not be serialized. By default all the variables in the object is converted to persistent state. In some cases, you may want to avoid persisting some variables because you don’t have the necessity to transfer across the network. So, you can declare those variables as transient. If the variable is declared as transient, then it will not be persisted. It is the main purpose of the transient keyword.
理解:默认情况下,对象中所有的变量都会转换为持久状态,但是有些情况变量在传输过程中是不需要进行持久化,这样你就可以将这些变量声明为transient变量。
Transient Keyword Example
package javabeat.samples; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class NameStore implements Serializable{ private String firstName; private transient String middleName; private String lastName; public NameStore (String fName, String mName, String lName){ this.firstName = fName; this.middleName = mName; this.lastName = lName; } public String toString(){ StringBuffer sb = new StringBuffer(40); sb.append("First Name : "); sb.append(this.firstName); sb.append("Middle Name : "); sb.append(this.middleName); sb.append("Last Name : "); sb.append(this.lastName); return sb.toString(); } } public class TransientExample{ public static void main(String args[]) throws Exception { NameStore nameStore = new NameStore("Steve", "Middle","Jobs"); ObjectOutputStream o = new ObjectOutputStream (new FileOutputStream("nameStore")); // writing to object o.writeObject(nameStore); o.close(); // reading from object ObjectInputStream in =new ObjectInputStream( new FileInputStream("nameStore")); NameStore nameStore1 = (NameStore)in.readObject(); System.out.println(nameStore1); } } // output will be : First Name : Steve Middle Name : null Last Name : Jobs
Look into the following example to understand the purpose of transient keyword:
/** * Save the state of the <tt>HashMap</tt> instance to a stream (i.e., * serialize it) * * @serialData The <i>capacity</i> of the HashMap (the length of the * bucket array) is emitted (int), followed by the * <i>size</i> (an int, the number of key-value * mappings), followed by the key (Object) and value (Object) * for each key-value mapping. The key-value mappings are * emitted in no particular order. */ private void writeObject(java.io.ObjectOutputStream s) throws IOException { Iterator<Map.Entry<K,V>> i = (size > 0) ? entrySet0().iterator() : null; // Write out the threshold, loadfactor, and any hidden stuff s.defaultWriteObject(); // Write out number of buckets s.writeInt(table.length); // Write out size (number of Mappings) s.writeInt(size); // Write out keys and values (alternating) if (i != null) { while (i.hasNext()) { Map.Entry<K,V> e = i.next(); s.writeObject(e.getKey()); s.writeObject(e.getValue()); } } }
三. 最后说一下为什么要将table域声明为transient
知乎上的一个回答最好理解,如下:
还有一个回答是国外网站上的,如下:
理解:主要原因是hashcode方法和JVM相关,在不同的操作平台有不同的实现。这样相同的键值在不同的平台计算出的哈希值有可能不一样。解决方法就是在序列话的时候将实体的内容进行持久化而不是table域,反序列化的时候再重新构建出HashMap对象。