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