天天看點

對象序列化流與對象反序列化流(ObjectOutputStream,ObjectInputStream)

這個連接配接包含了常用的流------IO流(總篇章)  
對象序列化:就是将對象儲存到磁盤中,或者在網絡中傳輸對象 這種機制就是使用一個位元組序清單示一個對象,該位元組序列包含:對象的類型、對象的資料和對象中存儲的屬性等資訊 位元組序列寫到檔案後,相當于檔案中持久儲存了一個對昂的資訊 反之。該位元組序列還可以從檔案中讀取回來,重構對象,對它進行反序列化
要實作序列化與反序列化,就要使用對象序列化流和對象反序列化流: 對象序列化流:ObjectOutputStream 對象反序列化流:ObjectInputStream
将Java對象的原始資料類型和圖像寫入OutputStream。可以使用ObjectInputStream讀取(重構)對象。可以通過使用流的檔案來實作對象的持久存儲。如果流是網絡套接字流,則可以再另外一個主機上或另一個程序中重構對象 構造方法:ObjectOutputStream(OutputStream out):建立一個寫入指定的OutputStream的ObjectOutputStream 序列化對象的方法:void writeObject(Object obj):将指定的對象寫入ObjectOutputStream
下面我們放代碼示範
學生類
序列化Demo
運作出現以下錯誤: Exception in thread "main" java.io.NotSerializableException: com.testIO.Student     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)     at com.testIO.ObjectOutputStreamDemo.main(ObjectOutputStreamDemo.java:13)
抛出一個執行個體需要Serializable接口。序列化運作時或執行個體的類可能會抛出此異常
類的序列化由實作java.io.Serializable接口的類啟用。不實作此接口的類将不會使任何狀态序列化或反序列化。可序列化類的所有子類型都是可序列化的。序列化接口沒有方法或字段,僅用于辨別可串行化的語義。
到這裡我們就明白報 java.io.NotSerializableException: com.testIO.Student異常的原因是,學生類Student沒有實作Serializable接口,下面我們把Student代碼修改一下,去實作Serializable接口。
再次運作,得到oos.txt檔案含有一下内容
對象序列化流與對象反序列化流(ObjectOutputStream,ObjectInputStream)
 到這裡,說明我們的序列化成功 一個對象要想被序列化,該對象所屬的類必須實作Serializable接口。 Serializable是一個标記接口,實作該接口,不需要重寫任何方法。
ObjectInputStream反序列化先前使用ObjectOutputStream編寫的原始資料和對象 構造方法:ObjectInputStream(InputStream in):建立從指定的InputStream讀取的ObjectInputStream 反序列化對象的方法:Object readObject():從ObjectInputStream讀取一個對象
輸出: 林高祿,27
到這裡,說明我們的反序列化成功
下面我們做一下騷修改,反序列化之前,我們對Student類做了些修改,比如重寫了toString()方法
再執行一次反序列化Demo,控制台報以下異常 Exception in thread "main" java.io.InvalidClassException: com.testIO.Student; local class incompatible: stream classdesc serialVersionUID = 5613672065288821876, local class serialVersionUID = 7003572463648716337     at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621)     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)     at com.testIO.ObjectInputStreamDemo.main(ObjectInputStreamDemo.java:12)
當序列化運作時檢測到類中的以下問題之一時抛出 類的串行版本與從流中讀取的類描述符的類型不比對 該類包含未知的資料類型 該類沒有可通路的無慘構造函數
stream classdesc serialVersionUID = 5613672065288821876, local class serialVersionUID = 7003572463648716337 從這裡我們知道,我們序列化是學生類的serialVersionUID = 5613672065288821876,而修改類後,local class serialVersionUID = 7003572463648716337,是以反序列異常
序列化運作時與每個可序列化的類關聯一個版本号,稱為serialVersionUID,它在反序列化的過程中使用,以驗證序列化對象的發送者和接收者是否加載了與序列化相容的對象的類。如果接收者已經具有與對應發件人類别不用的serialVersionUID的對象加載了一個類,則反序列化将導緻一個InvalidClassException。一個可序列化的類可以通過聲明一個名為“serialVersionUID”的字段來顯式地聲明它自己的serialVersionUID,該字段必須是static,final,和long類型。
知道原因之後,我們又修改了學生類,聲明serialVersionUID
執行序列化Demo之後,在修改Student類的代碼,比如重寫toString()方法,再執行反序列化Demo
林高祿,27,0
反序列化成功,但是我們發現bb=0,這是為什麼呢,注意看學生類屬性bb的定義, private transient int bb,關鍵字transient 作用就是使得修飾的屬性不被序列化,是以反序列得出來的值是預設值0。