父類的序列化與 Transient 關鍵字

情境:一個子類實現了 Serializable 接口,java

  • 它的父類都沒有實現 Serializable 接口,
  • 序列化該子類對象,
  • 而後反序列化後輸出父類定義的某變量的數值,該變量數值與序列化時的數值不一樣。

解決:函數

  • 要想將父類對象也序列化,就須要讓父類也實現Serializable 接口。
  • 若是父類不實現的話的,就 須要有默認的無參的構造函數。
    • 在父類沒有實現 Serializable 接口時,虛擬機是不會序列化父對象的,
    • 而一個 Java 對象的構造必須先有父對象,纔有子對象,反序列化也不例外。
    • 因此反序列化時,爲了構造父對象,只能調用父類的無參構造函數做爲默認的父對象。
    • 所以當咱們取父對象的變量值時,它的值是調用父類無參構造函數後的值。
      • 若是你考慮到這種序列化的狀況,在父類無參構造函數中對變量進行初始化,
      • 不然的話,父類變量值都是默認聲明的值,如 int 型的默認是 0,string 型的默認是 null。
  • 也就是說,要爲一個沒有實現Serializable接口的父類,編寫一個可以序列化的子類要作兩件事情: 

      其1、父類要有一個無參的constructor; 

      其2、子類要負責序列化(反序列化)父類的域。 
public abstract class SuperC { 
 int supervalue; 
 public SuperC(int supervalue) { 
  this.supervalue = supervalue; 
 }
 public SuperC(){}//增長一個無參的constructor 
  public String toString() { 
   return "supervalue: "+supervalue; 
  } 
 } 

 public class SubC extends SuperC implements Serializable { 
  int subvalue; 

  public SubC(int supervalue,int subvalue) { 
   super(supervalue); 
   this.subvalue=subvalue; 
  } 

  public String toString() { 
   return super.toString()+" sub: "+subvalue; 
  } 

  private void writeObject(java.io.ObjectOutputStream out) 
  throws IOException{ 
   out.defaultWriteObject();//先序列化對象 
   out.writeInt(supervalue);//再序列化父類的域 
  } 
  private void readObject(java.io.ObjectInputStream in) 
  throws IOException, ClassNotFoundException{ 
   in.defaultReadObject();//先反序列化對象 
   supervalue=in.readInt();//再反序列化父類的域 
  } 
}

 

Transient 關鍵字的做用是控制變量的序列化,this

  • 在變量聲明前加上該關鍵字,能夠阻止該變量被序列化到文件中,
  • 在被反序列化後,transient 變量的值被設爲初始值,如 int 型的是 0,對象型的是 null。
相關文章
相關標籤/搜索