序列化和反序列化
1、序列化和反序列化
(1)序列化:使用ObjectOutputStream類和writeObject( )方法,將一個對象變成字節(jié)流,用于存儲或網(wǎng)絡(luò)傳輸
(2)反序列化:使用ObjectInputStream類和readObject( )方法,將字節(jié)流"還原"成對象
(3)一個文件可以按照對象的數(shù)據(jù)格式保存一個或多個對象
2.1、實現(xiàn)接口:常用類基本直接或間接地實現(xiàn)了Serializable接口
(1)如果某個類需要進(jìn)行序列化和反序列化操作,必須實現(xiàn)Serializable【空實現(xiàn)】 或 Externalizable接口【序列化和反序列化兩個抽象方法】
(2)如果當(dāng)前類實現(xiàn)的序列化接口為Serializable 則必須擁有“序列化版本ID”
(3)如果當(dāng)前類實現(xiàn)的序列化接口為Externalizable(Serializable的子接口) 則不需要“序列化版本ID”
2.2、序列化和反序列化時,如果需要屏蔽某個屬性變量的方法
方式1:如果不希望某個屬性被序列化,則需要在聲明該屬性變量時,加入transient關(guān)鍵字。該方法適用于較少的屬性變量,方式簡單,效率較低。
方式2:實現(xiàn)Externalizable接口,進(jìn)行反序列化操作時,當(dāng)前類必須擁有一個無參構(gòu)造方法,并且需要實現(xiàn)序列化【writeExternal( )】和反序列化【readExternal ( )】兩個抽象方法,可自定義序列化哪些屬性。該方法適用于較多的屬性變量,方式較復(fù)雜,效率較高。
深淺拷貝
如果一個類的對象需要進(jìn)行克隆操作(淺拷貝或者深拷貝),則必須實現(xiàn)Cloneable接口,并且重寫clone()方法,如果沒有實現(xiàn)該接口則會拋出CloneNotSupportedException異常。
淺拷貝,重寫Object的克隆方法(修改返回值類型)
深拷貝(如果類A的屬性變量中含有類B的對象)
方式1:類A和類B都需實現(xiàn)Cloneable接口,并且重寫clone()方法,
克隆類A對象,克隆類B對象,將類B對象存入類A對象中,返回類A對象。
缺點:如果一個類中存在多個類的對象作為屬性變量,所有類都需要實現(xiàn)Cloneable接口,,并且重寫clone()方法,不斷向下復(fù)制。
方式2:使用序列化和反序列化實現(xiàn)”深拷貝”
類A和類B都需實現(xiàn)Serializable接口,并且添加序列化版本ID,類A自定義深拷貝方法。
將當(dāng)前對象轉(zhuǎn)換為字節(jié)流(序列化)
創(chuàng)建字節(jié)數(shù)組輸出流ByteArrayOutputStream對象bos
創(chuàng)建對象輸出流ObjectOutputStream對象oos
oos調(diào)用writeObject()將當(dāng)前對象寫入字節(jié)數(shù)組輸出流bos
將字節(jié)流轉(zhuǎn)換為新的對象(反序列化)
創(chuàng)建字節(jié)數(shù)組輸入流ByteArrayInputStream對象bis,將序列化后的字節(jié)數(shù)組輸出流bos轉(zhuǎn)換為字節(jié)數(shù)組并傳入
創(chuàng)建對象輸入流ObjectInputStream對象ois
ois調(diào)用readObject()并將當(dāng)前字節(jié)流強(qiáng)轉(zhuǎn)為新的對象