我們知道在java中,我們要將一個對象序列化以后,再將其反序列化以后就可以得到之前序列化之前的內(nèi)容.但是,假如我們有時并不是想讓某個類的所有的成員變量都要被序列化,那怎么辦呢?其中一種方法是使用靜態(tài)static
來修飾,另外一種就是今天要說的transient
這個關(guān)鍵字.
transient關(guān)鍵字能實現(xiàn)什么?
當(dāng)對象被序列化時(寫入字節(jié)序列到目標(biāo)文件)時顶燕,transient阻止實例中那些用此關(guān)鍵字聲明的變量持久化族操;當(dāng)對象被反序列化時(從源文件讀取字節(jié)序列進行,這樣的實例變量值不會被持久化和恢復(fù)。例如琅豆,當(dāng)反序列化對象——數(shù)據(jù)流(例如继谚,文件)可能不存在時,原因是你的對象中存在類型為java.io.InputStream
的變量畴椰,序列化時這些變量引用的輸入流無法被打開。-
如何使用transient鸽粉?
下面是一個小小的例子來簡要說明一下,就直接上代碼了:package com.rain.trainsent; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; public class TestTransient { public static void main(String[] args) throws FileNotFoundException, IOException { // TODO Auto-generated method stub Student s = new Student("zhangsan",12); System.out.println(s.toString()); //序列化 被設(shè)置為transient 沒有被序列化進去 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("student.txt")); o.writeObject(s); o.close(); //重新讀取序列化的內(nèi)容 ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt")); try { Student stu = (Student) in.readObject(); System.out.println(stu.toString()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Student implements Serializable{ private transient String name; private int id; public Student(String name, int id) { super(); this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Student [name=" + name + ", id=" + id + "]"; } }
可以看到,當(dāng)我們將這個類的name屬性用transient修飾后,當(dāng)我們將其序列化以后,反序列化的時候就得不到它之前的值了
-
transient使用細節(jié)——被transient關(guān)鍵字修飾的變量真的不能被序列化嗎斜脂?
看一下下面的一個例子:package com.rain.test; import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; public class TestTransient implements Externalizable { private transient String content="我會被序列化的,不管我有沒有被transient修飾"; public static void main(String[] args) throws ClassNotFoundException, IOException { TestTransient et = new TestTransient(); ObjectOutput out = new ObjectOutputStream(new FileOutputStream( new File("test"))); out.writeObject(et); ObjectInput in = new ObjectInputStream(new FileInputStream(new File( "test"))); et = (TestTransient) in.readObject(); System.out.println(et.content); out.close(); in.close(); } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(content); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { content = (String) in.readObject(); } }
我們知道在Java中,對象的序列化可以通過實現(xiàn)兩種接口來實現(xiàn)潜叛,若實現(xiàn)的是
Serializable
接口秽褒,則所有的序列化將會自動進行壶硅,若實現(xiàn)的是Externalizable
接口,則沒有任何東西可以自動序列化销斟,需要在writeExternal
方法中進行手工指定所要序列化的變量庐椒,這與是否被transient
修飾無關(guān).因此第二個例子輸出的是變量content初始化的內(nèi)容,而不是null.以上是個人對關(guān)鍵字transient的一些理解,希望能起到拋磚引玉的作用.