Java的serialization提供了一種持久化對象實例的機制。當持久化對象時,可能有一個特殊的對象數據成員,我們不想用serialization機制來保存它。為了在一個特定對象的一個域上關閉serialization,可以在這個域前加上關鍵字transient,transient是Java語言的關鍵字,用來表示一個域不是該對象串行化的一部分。當一個對象被串行化的時候,transient型變量的值不包括在串行化的表示中,然而非transient型的變量是被包括進去的。例如序列化對象的時候,有些屬性就不會序列化到指定的目的地中。像銀行卡、密碼等等這些數據。這個需要根據業務情況了。
具體案例可參考:java 中的關鍵字 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 write 10 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時,所期望的正確結果。
如果將pwd域前修飾符transient去掉,再做一次發現password內容會打印出傳入的參數內容,即:MECHANICS,也符合我們所期望的結果。
那到底什么時候使用這個關鍵字呢?處於什么考量呢,自己認為大概有以下兩點可以做考慮:
1. HashMap中的table中存儲的值數量是小於數組的大小的(數組擴容的原因),這個在元素越來越多的情況下更為明顯。如果使用默認的序列化,那些沒有元素的位置也會被存儲,就會產生很多不必要的浪費。
2. 對於HashMap來說(以及底層實現是利用HashMap的HashSet),由於不同的虛擬機對於相同hashCode產生的Code值可能是不一樣的,如果你使用默認的序列化,那么反序列化后,元素的位置和之前的是保持一致的,可是由於hashCode的值不一樣了,那么定位函數indexOf()返回的元素下標就會不同,這樣不是我們所想要的結果