1. 程式人生 > >java中transient關鍵字的作用

java中transient關鍵字的作用

java有個特點就是序列化,簡單地來說就是可以將這個類儲存在物理空間(當然還是以檔案的形式存在),那麼當你從本地還原這個檔案時,你可以將它轉換為它本身。這可以極大地方便網路上的一些操作,但同時,因為涉及到安全問題,所以並不希望把類裡面所有的東西都能儲存(因為那樣,別人可以通過序列化知道類裡面的內容),那麼我們就可以用上transient這個關鍵字,它的意思是臨時的,即不會隨類一起序列化到本地,所以當還原後,這個關鍵字定義的變數也就不再存在。

通常,我們寫的程式都要求特定資訊能持久存在或儲存到磁碟上,以供一個程式使用或用在同一個程式的另一次執行上.這種永續性可以通過幾種方式來實現,包括寫到資料庫中或是利用JAVA為物件序列化提供的支援.不管我們選用什麼方法,類例項的永續性都是通過儲存類的域的狀態來完成的,儲存這些狀態,以便以後可以對它們進行訪問或使用它們來建立相同的例項.然而,有可能並不是所有的域都需要被儲存起來.當一個例項被持久化時,其內部的一些域卻不需要持久化,則可以用trainsient修飾符告訴編譯器指定的域不需要被持久儲存.

首先,讓我們看一些Java serialization的程式碼:
public class LoggingInfo implements java.io.Serializable 

    private Date loggingDate = new Date(); 
    private String uid; 
    private transient String pwd; 
    
    LoggingInfo(String user, String password) 
    { 
        uid = user; 
        pwd = password; 
    } 
    public String toString() 
    { 
        String password=null; 
        if(pwd == null) 
        { 
        password = "NOT SET"; 
        } 
        else 
        { 
            password = pwd; 
        } 
        return "logon info: /n   " + "user: " + uid + 
            "/n   logging date : " + loggingDate.toString() + 
            "/n   password: " + password; 
    } 
}

現在我們建立一個這個類的例項,並且序列化(serialize)它 ,然後將這個序列化物件寫如磁碟。

LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS"); 
System.out.println(logInfo.toString()); 
try 

   ObjectOutputStream o = new ObjectOutputStream( 
                new FileOutputStream("logInfo.out")); 
   o.writeObject(logInfo); 
   o.close(); 

catch(Exception e) {//deal with exception}

To read the object back, we can write 

try 

   ObjectInputStream in =new ObjectInputStream( 
                new FileInputStream("logInfo.out")); 
   LoggingInfo logInfo = (LoggingInfo)in.readObject(); 
   System.out.println(logInfo.toString()); 

catch(Exception e) {//deal with exception}

如果我們執行這段程式碼,我們會注意到從磁碟中讀回(read——back (de-serializing))的物件列印password為"NOT SET"。這是當我們定義pwd域為transient時,所期望的正確結果。
現在,讓我們來看一下粗心對待transient域可能引起的潛在問題。假設我們修改了類定義,提供給transient域一個預設值,
程式碼如下:

public class GuestLoggingInfo implements java.io.Serializable 

    private Date loggingDate = new Date(); 
    private String uid; 
    private transient String pwd; 
    
    GuestLoggingInfo() 
    { 
        uid = "guest"; 
        pwd = "guest"; 
    } 
    public String toString() 
    { 
        //same as above 
     } 

現在,如果我們穿行化GuestLoggingInfo的一個例項,將它寫入磁碟,並且再將它從磁碟中讀出,我們仍然看到讀回的物件列印password 為 "NOT SET"。

當從磁碟中讀出某個類的例項時,實際上並不會執行這個類的建構函式,
而是載入了一個該類物件的持久化狀態,並將這個狀態賦值給該類的另一個物件。