咱們知道,當一個對象實現了Serilizable接口,這個對象就能夠被序列化,咱們不關心其內在的原理,只須要了解這個類實現了Serilizable接口,這個類的全部屬性和方法都會自動序列化。而在開發過程當中,咱們可能要求:當對象被序列化時(寫入字節序列到目標文件)時,有些屬性須要序列化,而其餘屬性不須要被序列化,打個比方,若是一個用戶有一些敏感信息(如密碼,銀行卡號等),爲了安全起見,不但願在網絡操做(主要涉及到序列化操做,本地序列化緩存也適用)中被傳輸,這些信息對應的變量就能夠加上transient關鍵字。換句話說,這個字段的生命週期僅存於調用者的內存中而不會寫到磁盤裏持久化。
因此,transient的用途在於:阻止實例中那些用此關鍵字聲明的變量持久化;當對象被反序列化時(從源文件讀取字節序列進行重構),這樣的實例變量值不會被持久化和恢復。例如,當反序列化對象——數據流(例如,文件)可能不存在時,緣由是你的對象中存在類型爲java.io.InputStream的變量,序列化時這些變量引用的輸入流沒法被打開。html
序列化的時候,將不須要序列化的屬性前添加關鍵字transient便可。
示例:java
package newDay.day13; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class UserInfo implements Serializable { private static final long serialVersionUID = 996890129747019948L; private String name; private transient String psw; public UserInfo(String name, String psw) { this.name = name; this.psw = psw; } public String toString() { return "name=" + name + ", psw=" + psw; } } public class TestTransient { public static void main(String[] args) { UserInfo userInfo = new UserInfo("張三", "123456"); System.out.println(userInfo); try { // 序列化,被設置爲transient的屬性沒有被序列化 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt")); o.writeObject(userInfo); o.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } try { // 從新讀取內容 ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt")); UserInfo readUserInfo = (UserInfo) in.readObject(); //讀取後psw的內容爲null System.out.println(readUserInfo.toString()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
運行結果:web
name=張三, psw=123456 name=張三, psw=null
密碼字段爲null,說明被標記爲transient的屬性在對象被序列化的時候不會被保存。緩存
1,一旦變量被transient修飾,變量將再也不是對象持久化的一部分,該變量內容在序列化後沒法得到訪問。
2,transient關鍵字只能修飾變量,而不能修飾方法和類。注意,本地變量是不能被transient關鍵字修飾的。變量若是是用戶自定義類變量,則該類須要實現Serializable接口。
3,被transient關鍵字修飾的變量再也不能被序列化,一個靜態變量無論是否被transient修飾,均不能被序列化。
對於第三點,加上static以後,依然能把姓名輸出。這是由於:反序列化後類中static型變量name的值爲當前JVM中對應static變量的值,這個值是JVM中的不是反序列化得出的。下例可說明,其值時JVM中獲得的而不是反序列化獲得的:安全
package newDay.day13; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class UserInfo implements Serializable { private static final long serialVersionUID = 996890129747019948L; private static String name; private transient String psw; public UserInfo(String name, String psw) { this.name = name; this.psw = psw; } public static String getName() { return name; } public static void setName(String name) { UserInfo.name = name; } public String getPsw() { return psw; } public void setPsw(String psw) { this.psw = psw; } public String toString() { return "name=" + name + ", psw=" + psw; } } public class TestTransient { public static void main(String[] args) { UserInfo userInfo = new UserInfo("張三", "123456"); System.out.println(userInfo); try { // 序列化,被設置爲transient的屬性沒有被序列化 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt")); o.writeObject(userInfo); o.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } try { //在反序列化以前改變name的值 userInfo.setName("hello"); // 從新讀取內容 ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt")); UserInfo readUserInfo = (UserInfo) in.readObject(); //讀取後psw的內容爲null System.out.println(readUserInfo.toString()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
運行結果:網絡
name=張三, psw=123456 name=hello, psw=null
這說明反序列化後類中static型變量name的值爲當前JVM中對應static變量的值,爲修改後hello,而不是序列化時的值「張三」ide