對象的序列化與反序列化

Java的對象的序列化將那些實現(xiàn)了serializable接口的對象轉(zhuǎn)換成一個字節(jié)序列,并能夠在以后將這個字節(jié)序列恢復(fù)為原來的對象
(序列化能通過網(wǎng)絡(luò)進(jìn)行,彌補(bǔ)不同操作系統(tǒng)之間的差異)


簡而言之:
對象序列化就是講object轉(zhuǎn)換成byte序列,反之叫對象的反序列化。

具體步驟:
序列化:

  1. 創(chuàng)建OutputStream對象
  2. 封裝在一個ObjectOutputStream對象內(nèi)。
  3. 調(diào)用writeObject()方法,并將其發(fā)送給OutputStream
        String file = "demo/obj.dat";
        //1.對象的序列化
        ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(file));
        Student stu = new Student("10001", "張三", 20);
        oos.writeObject(stu);
        oos.flush();
        oos.close();

反序列化:

  1. 創(chuàng)建InputStream對象
  2. 封裝在一個ObjectIntputStream對象內(nèi)。
  3. 調(diào)用readObject()方法,并將其發(fā)送給InputStream
        String file = "demo/obj.dat";
ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(file));
        Student stu = (Student)ois.readObject();
        System.out.println(stu);
        ois.close();

transient(順時)關(guān)鍵字

當(dāng)我們隊序列化進(jìn)行控制時,可能某個特定子對象不想讓Java的序列化機(jī)制自動保存與恢復(fù)如果子對象表示的是我們不希望將其序列化的敏感信息(如密碼),通常就會面臨這種情況。及時對象中的這些信息是private屬性,一經(jīng)序列化處理,人們就可以通過讀取文件或者攔截網(wǎng)絡(luò)傳輸?shù)姆绞降玫剿?br> 為了能夠加以控制,可以用transient關(guān)鍵字逐個字段地關(guān)閉序列化他的意思是不用麻煩保存或者回復(fù)數(shù)據(jù),我自己會處理好。
示例:
//該元素不會進(jìn)行jvm默認(rèn)的序列化,也可以自己完成這個元素的序列化 private transient int stuage;

可以自己進(jìn)行序列化和反序列化:

實現(xiàn)了Serializable接口的對象,并添加(不是覆蓋或者實現(xiàn))writeObject()和readObject()(private)方法。如此,一旦對象被序列化和反序列化時,會自動調(diào)用這兩個方法,而不是默認(rèn)的反序列化機(jī)制。
此外:在兩個方法內(nèi)部可以分別調(diào)用defaultWriteObject()來執(zhí)行默認(rèn)的writeObject(),defaultReadObject()來執(zhí)行默認(rèn)的readObject()

 private void writeObject(java.io.ObjectOutputStream s)
                throws java.io.IOException{
         s.defaultWriteObject();//把jvm能默認(rèn)序列化的元素進(jìn)行序列化操作
         s.writeInt(stuage);//自己完成stuage的序列化
     }

 private void readObject(java.io.ObjectInputStream s)
                throws java.io.IOException, ClassNotFoundException{
          s.defaultReadObject();//把jvm能默認(rèn)反序列化的元素進(jìn)行反序列化操作
          this.stuage = s.readInt();//自己完成stuage的反序列化操作
    }

序列化中子類和父類構(gòu)造函數(shù)的調(diào)用問題

結(jié)論一. 序列化會依次調(diào)用父類構(gòu)造函數(shù)
測試對象:

class Foo implements Serializable{  
    public Foo(){
        System.out.println("foo...");
    }
}
class Foo1 extends Foo {
    public Foo1(){
        System.out.println("foo1...");
    }
}
class Foo2 extends Foo1{
    public Foo2(){
        System.out.println("foo2...");
    }
}
class Bar{
    public Bar(){
        System.out.println("bar");
    }
}
class Bar1 extends Bar{
    public Bar1(){
        System.out.println("bar1..");
    }
}
class Bar2 extends Bar1 implements Serializable{
    public Bar2(){
        System.out.println("bar2...");
    }
測試代碼
輸出結(jié)果

結(jié)論二. 對子類對象進(jìn)行反序列化操作時, 如果其父類沒有實現(xiàn)序列化接口, 那么其父類的構(gòu)造函數(shù)會被調(diào)用*
測試代碼:

測試一
結(jié)果一
測試二
結(jié)果二
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容