java 序列化與反序列化

什么是序列化

(1)序列化是將對(duì)象轉(zhuǎn)變?yōu)樽止?jié)序列的過程,反序列化則是將字節(jié)序列恢復(fù)為對(duì)象的過程。

(2)對(duì)象序列化保存的是對(duì)象的狀態(tài),即它的成員變量;

(3)對(duì)象的持久化存儲(chǔ)(寫文件),網(wǎng)絡(luò)傳輸對(duì)象,或者使用RMI都會(huì)用到對(duì)象序列化。



JAVA 提供的操作序列化的接口

(1)Java 主要提供給了兩個(gè)接口實(shí)現(xiàn)對(duì)象的序列化和反序列化,java.io.ObjectInputStream的readObject()方法?和 java.io.ObjectOutputStream 的writeObject(Object obj)方法;

(2)只有實(shí)現(xiàn)Serializable或Externalizable接口的類的對(duì)象才能被序列化;否則會(huì)拋出java.io.NotSerializableException異常。



JAVA對(duì)象序列化示例


(1)類實(shí)現(xiàn) Serializable接口

?類中未定義 writeObject(Object obj)和readObject方法,那么按照默認(rèn)的序列化方式實(shí)現(xiàn)序列化和反序列化。


Student.java


Gender.java


SimpleSerializable.java

以上代碼展示了如何序列化對(duì)象到一個(gè)文件中并從文件中反序列化的過程。

序列化的過程:

首先創(chuàng)建 ObjectOutputStream 對(duì)象,該對(duì)象可以包裝其他輸出流,比如文件輸出流;

調(diào)用對(duì)象輸出流的writeObject(Object obj)方法,可以將對(duì)象寫入到輸出流中。

關(guān)閉流。結(jié)束。

對(duì)象持久化到文件中的過程結(jié)束。

反序列化的過程:

首先創(chuàng)建ObjectInputStream對(duì)象,類似于ObjectOutputStream;

調(diào)用對(duì)象輸入流的readObject()方法,讀對(duì)象到輸入流中。返回字節(jié)序列轉(zhuǎn)化的對(duì)象。

關(guān)閉流;結(jié)束。

輸出:

result



?類中定義了 writeObject(Object obj)和readObject方法,那么按照自定義的序列化方實(shí)現(xiàn)式序列化和反序列化。

在Student.java添加如下兩個(gè)方法:


user-dined_read_write_Object

輸出結(jié)果:

result2


(2)transient?關(guān)鍵字

? 當(dāng)某個(gè)成員變量聲明為transient后,默認(rèn)的序列化機(jī)制就會(huì)忽略該變量。

將age字段聲明為transient,

transient

輸出 age=0:

result3


此時(shí)我們可以選擇單獨(dú)傳輸某個(gè)字段;修改writeObject和readObject方法:


結(jié)果:

result4

單獨(dú)傳輸了age 字段,因此age=18;

補(bǔ)充:除了上面提到的兩個(gè)方法外:

private void writeObject(java.io.ObjectOutputStream out)?throws IOException ;

private void readObject(java.io.ObjectInputStream in)?throws IOException, ClassNotFoundException;

還有其他三個(gè)方法,可供我們定制自己的序列化反序列化過程:

private void readObjectNoData()?throws ObjectStreamException;

ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

readObjectNoData() :用于初始化反序列化對(duì)象,當(dāng)發(fā)生一些情況導(dǎo)致反序列化對(duì)象不能獲得數(shù)據(jù)時(shí)調(diào)用;

writeReplace() 指派其他對(duì)象寫入序列化的流中;

readResolve()返回的對(duì)象替換反序列化創(chuàng)建的實(shí)例;


readResolve() 常用于單例模式中;示例:

修改Student.java,添加instanceHoder:

Student.java


Student.java

修改SimpleSerial.java:


SimpleSerial.java

結(jié)果輸出:

result5

可以看到,s==student返回false,也就是說反序列化后得到的Student對(duì)象并不是唯一的instance,因此這樣寫單例模式是失敗的;

修正:

readResolve

再次運(yùn)行:

result6


總結(jié):

當(dāng)進(jìn)行序列化的時(shí)候:

首先JVM會(huì)先調(diào)用writeReplace方法,在這個(gè)階段,我們可以進(jìn)行張冠李戴,將需要進(jìn)行序列化的對(duì)象換成我們指定的對(duì)象.

跟著JVM將調(diào)用writeObject方法,來將對(duì)象中的屬性一個(gè)個(gè)進(jìn)行序列化,我們可以在這個(gè)方法中控制住哪些屬性需要序列化.

當(dāng)反序列化的時(shí)候:

JVM會(huì)調(diào)用readObject方法,將我們剛剛在writeObject方法序列化好的屬性,反序列化回來.

然后在readResolve方法中,我們也可以指定JVM返回我們特定的對(duì)象(不是剛剛序列化回來的對(duì)象).

注意到在writeReplace和readResolve,我們可以嚴(yán)格控制singleton的對(duì)象,在同一個(gè)JVM中完完全全只有唯一的對(duì)象,控制不讓singleton對(duì)象產(chǎn)生副本.


(3)類實(shí)現(xiàn)Externalizable 接口?

? ?Externalizable 接口繼承 Serializable接口:?

public interface Externalizable extends?Serializable?;

Serializable接口是一個(gè)mark interface,沒有實(shí)際方法;而Externalizable 接口提供了兩個(gè)方法:

void ?readExternal?(ObjectInput?in) ;

void ?writeExternal?(ObjectOutput?out) ;

readExternal (ObjectInput in):從輸入流中讀取內(nèi)容恢復(fù)對(duì)象;

writeExternal?(ObjectOutput?out) : 寫入對(duì)象到輸出流中;

示例:


Externalizable

使用Externalizable進(jìn)行序列化時(shí),當(dāng)讀取對(duì)象時(shí),會(huì)調(diào)用被序列化類的無參構(gòu)造器去創(chuàng)建一個(gè)新的對(duì)象,然后再將被保存對(duì)象的字段的值分別填充到新對(duì)象中。因此,必須提供一個(gè)無參構(gòu)造器,訪問權(quán)限為public;否則會(huì)拋出java.io.InvalidClassException 異常;

總結(jié):Externalizable接口實(shí)現(xiàn)的功能與Serializable接口類似,Serializable序列化時(shí)不會(huì)調(diào)用默認(rèn)的構(gòu)造器,而Externalizable序列化時(shí)會(huì)調(diào)用默認(rèn)構(gòu)造器;


感謝:深入理解Java對(duì)象序列化 - 51CTO.COM

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評(píng)論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,368評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,235評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,427評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,656評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評(píng)論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,160評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,380評(píng)論 2 379

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

  • 在Java中,我們可以通過多種方式來創(chuàng)建對(duì)象,并且只要對(duì)象沒有被回收我們都可以復(fù)用該對(duì)象。但是,我們創(chuàng)建出來的這些...
    懶癌正患者閱讀 1,537評(píng)論 0 12
  • 序列化的意義 1.永久存儲(chǔ)某個(gè)jvm中運(yùn)行時(shí)的對(duì)象。2.對(duì)象可以網(wǎng)絡(luò)傳輸3.rmi調(diào)用都是以序列化的方式傳輸參數(shù) ...
    炫邁哥閱讀 663評(píng)論 0 0
  • 什么是序列化與反序列化 序列化是指把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程(Encoding an object as a by...
    小X感悟閱讀 892評(píng)論 0 4
  • java序列化與反序列化 對(duì)象序列化是一種持久化技術(shù),廣泛運(yùn)用于網(wǎng)絡(luò)傳輸、RMI等場(chǎng)景中。java對(duì)象存在于JVM...
    Crazy貴子閱讀 635評(píng)論 0 0
  • 一、序列化和反序列化的概念 把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化。把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列...
    叨唧唧的閱讀 724評(píng)論 0 0