1. 程式人生 > >java中的序列化與transient關鍵字

java中的序列化與transient關鍵字

    序列化和transient關鍵字應該屬於java中較高階的話題,筆者(ymh)今天花一點時間小結一些這部分知識,希望能給初學者一些幫助。若有錯誤希望指出,學無止境。轉載請註明出處!

什麼是序列化?

      序列化 (Serialization)將物件的狀態資訊轉換為可以儲存或傳輸的形式的過程。在序列化期間,物件將其當前狀態寫入到臨時或永續性儲存區。以後,可以通過從儲存區中讀取或反序列化物件的狀態,重新建立該物件。

如何實現序列化?

    java中要想一個類的例項能夠被序列化,則該類可以實現Serializable介面,這是一個空介面,其中並沒有任何需要實現的方法,僅用來在編譯時讓編譯器標識該類的例項可被序列化,實現Serializable介面的類的例項屬性將自動參與序列化過程。

   另外,java類也可以實現Externalizable介面,該介面是Serializable介面的子介面,有兩個抽象方法:

實現Externalizable介面的java類需要writeExternal方法中明確指定哪些屬性要參與序列化過程。

transient關鍵字的用途?

     transient關鍵字只能用於修飾變數,不能修飾方法和類。若一個類中有些屬性需要被序列化,應先實現Serializable介面,而有一些屬性包含敏感資訊,如密碼、銀行卡號等,這些資訊若不想被序列化,可以用transient關鍵字修飾。被transient修飾的屬性將不參與序列化過程。

Serializable介面配合transient關鍵字使用案例:

public class SerializationDemo {
 
   final static class Person implements Serializable{
    private transient String id;  //transient修飾的例項屬性
    private String name;
    private static int count;
    private static transient String desc; //transient修飾的類屬性
    public Person(){}
    public Person(String id,String name,int count1,String desc1)
    {
     this.id=id;
     this.name=name;
     count=count1;
     desc=desc1;
    }
   }
  
 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
  System.out.println(“序列化:將物件寫入檔案”);
 Person person=new Person(UUID.randomUUID().toString(), “張三”, 11, “我是張三”);
 System.out.println(“transient修飾的例項屬性:”+person.id);
 System.out.println(“普通例項屬性:”+person.name);
 System.out.println(“普通類屬性:”+person.count);
 System.out.println(“transient修飾的類屬性:”+person.desc);
 //序列化
 File objectFile=new File(“f:/mm.txt”);
 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(objectFile));
 oos.writeObject(person);
 oos.close();
 person=null;
 //反序列化
 System.out.println(“反序列化:從檔案中讀取物件”);
 Person.count=22;
 ObjectInputStream ois=new ObjectInputStream(new FileInputStream(objectFile));
 person=(Person) ois.readObject();
 System.out.println(“transient修飾的例項屬性:”+person.id);
 System.out.println(“普通例項屬性:”+person.name);
 System.out.println(“普通類屬性:”+person.count);
 System.out.println(“transient修飾的類屬性:”+person.desc);
 ois.close();
}
  
}

輸出結果:

結論:

1、對於例項屬性來說,被transient修飾的例項屬性將不會參與序列化。

2、對於類屬性來說,無論類屬性是否被transient關鍵字修飾,類屬性都不會參加序列化過程。

可以這樣理解:序列化是針對物件的操作過程,而類屬性是屬於類的一部分,不屬於某個具體的例項,因此類屬性不參與序列化。

上面測試程式碼也很好的佐證了這一觀點,因為若類屬效能夠被序列化,則反序列化讀取到的類屬性值應該與序列化時寫入的類屬性值一致,但程式碼中反序列化前修改了類屬性值,反序列化讀取到的該類屬性值跟著變化,說明該類屬性的值並不是從反序列化的過程中讀取到的,實際上是從JVM的方法區中讀取的。