源碼中transient的用途,源碼transient用途
Java的serialization提供了一種持久化對象執行個體的機制。當持久化對象時,可能有一個特殊的對象資料成員,我們不想用serialization機制來儲存它。為了在一個特定對象的一個域上關閉serialization,可以在這個域前加上關鍵字transient,transient是Java語言的關鍵字,用來表示一個域不是該對象序列化的一部分。當一個對象被序列化的時候,transient型變數的值不包括在序列化的表示中,然而非transient型的變數是被包括進去的。
那麼,讓我們看一下序列化的代碼如下:
1 public class LoggingInfo implements java.io.Serializable { 2 private Date loggingDate = new Date(); 3 private String uid; 4 private transient String pwd; 5 6 LoggingInfo(String user, String password) { 7 uid = user; 8 pwd = password; 9 } 10 public String toString() { 11 String password=null; 12 if(pwd == null) { 13 password = "NOT SET"; 14 } 15 else { 16 password = pwd; 17 } 18 return "logon info: \n " + "user: " + uid + 19 "\n logging date : " + loggingDate.toString() + 20 "\n password: " + password;21 }22 }
現在我們再建立一個這個類的執行個體,並且序列化(serialize)它 ,然後將這個序列化對象寫如磁碟。
1 LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS"); 2 System.out.println(logInfo.toString()); 3 try { 4 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("logInfo.out")); 5 o.writeObject(logInfo); 6 o.close(); 7 } 8 catch(Exception e) {//deal with exception} 9 To read the object back, we can write10 try {11 ObjectInputStream in =new ObjectInputStream(new FileInputStream("logInfo.out"));12 LoggingInfo logInfo = (LoggingInfo)in.readObject();13 System.out.println(logInfo.toString());14 }15 catch(Exception e) {//deal with exception}
運行這段代碼,我們會注意到從磁碟中讀回(read——back (de-serializing))的對象列印password為"NOT SET"。這是當我們定義pwd域為transient時,所期望的正確結果。如果將password前修飾符transient去掉,再做一次發現password不會打出任何內容。
那到底什麼時候使用這個關鍵字呢?處於什麼考量呢,自己認為大概有以下兩點可以做考慮:
1. HashMap中的table中儲存的值數量是小於數組的大小的(數組擴容的原因),這個在元素越來越多的情況下更為明顯。如果使用預設的序列化,那些沒有元素的位置也會被儲存,就會產生很多不必要的浪費。
2. 對於HashMap來說(以及底層實現是利用HashMap的HashSet),由於不同的虛擬機器對於相同hashCode產生的Code值可能是不一樣的,如果你使用預設的序列化,那麼還原序列化後,元素的位置和之前的是保持一致的,可是由於hashCode的值不一樣了,那麼定位函數indexOf()返回的元素下標就會不同,這樣不是我們所想要的結果