Android 序列化 & 反序列化

What叭首?

何為序列化與反序列化?
序列化:將對(duì)象轉(zhuǎn)化為二進(jìn)制序列的過(guò)程
反序列化:將二進(jìn)制序列恢復(fù)為原始對(duì)象的過(guò)程

Why踪栋?

為什么需要序列化焙格?
由于在系統(tǒng)底層,數(shù)據(jù)以簡(jiǎn)單的字節(jié)序列形式進(jìn)行傳遞夷都,即在底層眷唉,系統(tǒng)不認(rèn)識(shí)對(duì)象,只認(rèn)識(shí)字節(jié)序列囤官,所以為了達(dá)到跨進(jìn)程通訊的目的冬阳,需要先對(duì)數(shù)據(jù)進(jìn)行序列化;其次党饮,在進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸或者activity間對(duì)象傳遞時(shí)肝陪,也需要先將對(duì)象轉(zhuǎn)化為字節(jié)序列。

How刑顺?

如何進(jìn)行序列化氯窍?
在Android中饲常,序列化操作有兩種方式:實(shí)現(xiàn)Serializabale接口或?qū)崿F(xiàn)Parcelable接口。
Serializabale接口
Serializabale接口是一個(gè)空接口狼讨,實(shí)際上只提供標(biāo)記的功能贝淤,標(biāo)記實(shí)現(xiàn)了該接口的對(duì)象是可以進(jìn)行序列化的,而具體的序列化與反序列化操作是由ObjectOutputStream和ObjectInputStream完成的政供。序列化與反序列化過(guò)程均對(duì)用戶(hù)透明播聪,其中需要保存許多額外的字段以保證反序列化過(guò)程能夠順利完成,同時(shí)布隔,在這個(gè)過(guò)程中犬耻,還涉及到Java反射機(jī)制,所以整體時(shí)空開(kāi)銷(xiāo)比較大执泰。
Parcelable接口
Parcelable是Android提供的接口枕磁,它主要是通過(guò)writeToParcel(),將需要持久化的字段保存到一個(gè)Parcel對(duì)象里面术吝,然后通過(guò)CREATOR從Parcel對(duì)象中计济,取出相應(yīng)的字段,完成對(duì)象的恢復(fù)過(guò)程排苍。這整個(gè)過(guò)程均由用戶(hù)自己控制沦寂,可以自定義保存和恢復(fù)的字段,所以存儲(chǔ)代價(jià)小很多淘衙。
Serializabale VS Parcelable
實(shí)際開(kāi)發(fā)中传藏,推薦使用Parcelable接口,理由大致有如下三點(diǎn):首先彤守,Parcelable接口是Android提供使用的毯侦,Google提供了比較好的文檔和技術(shù)支持;其次具垫,Parcelable接口底層是內(nèi)存的copy侈离,而Serializable底層是文件IO操作,同時(shí)會(huì)使用到反射技術(shù)筝蚕,所以效率上卦碾,Parcelable要遠(yuǎn)高于Serializable;最后起宽,Parcelable具有更好地可控性洲胖,我們可以自己控制需要保存和恢復(fù)的字段,同時(shí)節(jié)省空間開(kāi)銷(xiāo)坯沪。Parcleable主要用于內(nèi)存序列化绿映,通過(guò)Parcelable將對(duì)象序列化到存儲(chǔ)設(shè)備中或者將對(duì)象序列化后通過(guò)網(wǎng)絡(luò)進(jìn)行傳輸也是可以的,但是這個(gè)過(guò)程會(huì)稍顯復(fù)雜屏箍,因此在這兩種情況下绘梦,建議使用Serializable橘忱。

序列化相關(guān)知識(shí)

  1. 序列化 ID
    當(dāng)通過(guò)實(shí)現(xiàn)Serializable接口實(shí)現(xiàn)類(lèi)的序列化操作時(shí),需要提供一個(gè)序列化ID卸奉,即聲明private static final long serialVersionUID钝诚,原則上序列化后的數(shù)據(jù)中的serialVersionUID只有和當(dāng)前類(lèi)的serialVersionUID相同時(shí),才能夠進(jìn)行正常的反序列化操作榄棵,否則反序列化過(guò)程會(huì)失敗凝颇。serialVersionUID的詳細(xì)工作機(jī)制為:序列化的時(shí)候,系統(tǒng)會(huì)將當(dāng)前類(lèi)的serialVersionUID寫(xiě)入序列化文件/指定文件中疹鳄,當(dāng)反序列化的時(shí)候拧略,系統(tǒng)會(huì)檢測(cè)文件中的serialVersionUID與當(dāng)前類(lèi)中的serialVersionUID是否一致,若一致瘪弓,說(shuō)明序列化的類(lèi)的版本與當(dāng)前類(lèi)的版本相同垫蛆,這個(gè)時(shí)候可以成功進(jìn)行反序列化操作;否則腺怯,說(shuō)明當(dāng)前類(lèi)和序列化的類(lèi)相比袱饭,發(fā)生了某些變化,如成員變量的數(shù)量呛占、類(lèi)型等發(fā)生變化虑乖,這時(shí)反序列化操作就無(wú)法正常完成。

  2. 靜態(tài)變量序列化
    靜態(tài)變量是類(lèi)變量晾虑,不屬于某個(gè)對(duì)象疹味,而序列化操作保存的是對(duì)象的狀態(tài),即對(duì)象的成員變量帜篇,所以靜態(tài)變量不會(huì)參與序列化過(guò)程糙捺。

  3. 父類(lèi)的序列化
    如果希望一個(gè)類(lèi)的父類(lèi)也被序列化,則該父類(lèi)也應(yīng)實(shí)現(xiàn)序列化接口坠狡。

  4. Transient 關(guān)鍵字
    Transient用于聲明一個(gè)變量不參與序列化過(guò)程继找,所以當(dāng)希望某些變量不被序列化時(shí),就可以使用該關(guān)鍵字修飾這些變量逃沿。被Transient關(guān)鍵字聲明的變量,在反序列化時(shí)幻锁,會(huì)被設(shè)置為初始值凯亮,即int類(lèi)型變量為0,對(duì)象類(lèi)型變量為null哄尔。

  5. 對(duì)敏感字段加密
    在消息傳輸?shù)倪^(guò)程中假消,有些字段是敏感字段,不希望被泄露岭接,如用戶(hù)密碼等富拗,在這種情況下臼予,進(jìn)行序列化操作時(shí),應(yīng)先對(duì)敏感字段進(jìn)行加密操作啃沪,反序列化時(shí)再進(jìn)行解密粘拾。具體解決辦法為:重寫(xiě)類(lèi)中的writeObject和readObject方法。因?yàn)樵谛蛄谢^(guò)程中创千,虛擬機(jī)會(huì)先調(diào)用待序列化類(lèi)中的writeObject和readObject方法缰雇,若該方法存在,則使用該方法完成用戶(hù)自定義的序列化和反序列化操作追驴,否則械哟,調(diào)用 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法進(jìn)行默認(rèn)的序列化和反序列化操作。

  6. 序列化存儲(chǔ)規(guī)則
    Java 序列化機(jī)制為了節(jié)省磁盤(pán)空間殿雪,具有特定的存儲(chǔ)規(guī)則暇咆,當(dāng)對(duì)同一對(duì)象進(jìn)行多次序列化操作時(shí),并不會(huì)對(duì)該對(duì)象的內(nèi)容進(jìn)行多次存儲(chǔ)丙曙,而只存儲(chǔ)多份引用糯崎,這樣就只需要保存新增的引用及一些控制信息。

ArrayList的序列化

ArrayList的定義
ArrayList保存內(nèi)容的數(shù)組

由上圖一可知河泳,ArrayList實(shí)現(xiàn)了Serializable接口沃呢,可以進(jìn)行序列化操作,而由圖二可知拆挥,其中保存內(nèi)容的數(shù)組array被transient關(guān)鍵字修飾薄霜,不會(huì)被序列化,那么問(wèn)題來(lái)了纸兔,這到底是咋回事呢惰瓜?
原因如下圖三所示:

圖三

ArrayList內(nèi)部實(shí)現(xiàn)了writeObject和readObject方法,通過(guò)這兩個(gè)方法自己控制序列化過(guò)程汉矿。
Why transient崎坊?
ArrayList為什么使用transient使array不被序列化,然后又自定義序列化過(guò)程呢洲拇?
因?yàn)锳rrayList是一個(gè)動(dòng)態(tài)數(shù)組奈揍,經(jīng)常會(huì)成倍自增長(zhǎng)長(zhǎng)度,當(dāng)數(shù)組中實(shí)際存放的元素很少赋续,而申請(qǐng)的長(zhǎng)度比較大時(shí)男翰,直接進(jìn)行序列化,就會(huì)生成很多null元素纽乱,所以為了避免不必要的null元素的生成蛾绎,及提高時(shí)空效率,ArrayList將array用transient關(guān)鍵字進(jìn)行聲明,然后再自己控制元素的序列化過(guò)程租冠。

總結(jié)

  1. 在進(jìn)行跨進(jìn)程通信鹏倘、activity間數(shù)據(jù)傳輸以及網(wǎng)絡(luò)數(shù)據(jù)傳輸時(shí),需要將原始的對(duì)象類(lèi)型轉(zhuǎn)化為字節(jié)序列顽爹,這是就需要使用到對(duì)象的序列化與反序列化操作纤泵;
  2. 序列化即將對(duì)象或數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為字節(jié)序列的過(guò)程;反序列化即將字節(jié)序列恢復(fù)為原始對(duì)象的過(guò)程话原;序列化保存的是對(duì)象的“狀態(tài)”夕吻,即對(duì)象的成員變量,所以靜態(tài)變量繁仁、靜態(tài)方法等屬于類(lèi)的屬性以及被transient關(guān)鍵字聲明的不用于序列化的屬性涉馅,均不會(huì)被序列化;
  3. Android中序列化操作有兩種方式:實(shí)現(xiàn)Serializable接口和實(shí)現(xiàn)Parcleable接口黄虱。Serialiable是Java提供的序列化接口,使用起來(lái)比較簡(jiǎn)單稚矿,但是開(kāi)銷(xiāo)很大,序列化和反序列化均需要大量I/O操作捻浦,而Parcelable是Android提供的序列化方式晤揣,因此更適合用于Android平臺(tái),所以在Android平臺(tái)上朱灿,首選Parcelable接口昧识。
  4. ArrayList的序列化過(guò)程比較特殊,需要注意盗扒。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末跪楞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子侣灶,更是在濱河造成了極大的恐慌甸祭,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褥影,死亡現(xiàn)場(chǎng)離奇詭異池户,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)凡怎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)校焦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人栅贴,你說(shuō)我怎么就攤上這事斟湃。” “怎么了檐薯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我坛缕,道長(zhǎng)墓猎,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任赚楚,我火速辦了婚禮毙沾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宠页。我一直安慰自己左胞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布举户。 她就那樣靜靜地躺著烤宙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俭嘁。 梳的紋絲不亂的頭發(fā)上躺枕,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音供填,去河邊找鬼拐云。 笑死,一個(gè)胖子當(dāng)著我的面吹牛近她,可吹牛的內(nèi)容都是我干的叉瘩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼粘捎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼薇缅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起晌端,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捅暴,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后咧纠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蓬痒,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年漆羔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梧奢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡演痒,死狀恐怖亲轨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸟顺,我是刑警寧澤惦蚊,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布器虾,位于F島的核電站,受9級(jí)特大地震影響蹦锋,放射性物質(zhì)發(fā)生泄漏兆沙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一莉掂、第九天 我趴在偏房一處隱蔽的房頂上張望葛圃。 院中可真熱鬧,春花似錦憎妙、人聲如沸库正。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)褥符。三九已至,卻和暖如春阅嘶,著一層夾襖步出監(jiān)牢的瞬間属瓣,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工讯柔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抡蛙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓魂迄,卻偏偏與公主長(zhǎng)得像粗截,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捣炬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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

  • JAVA序列化機(jī)制的深入研究 對(duì)象序列化的最主要的用處就是在傳遞,和保存對(duì)象(object)的時(shí)候,保證對(duì)象的完整...
    時(shí)待吾閱讀 10,837評(píng)論 0 24
  • 官方文檔理解 要使類(lèi)的成員變量可以序列化和反序列化熊昌,必須實(shí)現(xiàn)Serializable接口。任何可序列化類(lèi)的子類(lèi)都是...
    獅_子歌歌閱讀 2,386評(píng)論 1 3
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1湿酸、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2婿屹、Andro...
    隔壁老李頭閱讀 11,783評(píng)論 6 38
  • 由于進(jìn)行通信肯定要涉及數(shù)據(jù)的處理,所以我們需要先了解兩個(gè)基礎(chǔ)的概念推溃,序列化和反序列化昂利。 定義 序列化:將對(duì)象轉(zhuǎn)化為...
    Eric_feng閱讀 1,135評(píng)論 0 1
  • 如果你只知道實(shí)現(xiàn) Serializable 接口的對(duì)象,可以序列化為本地文件铁坎。那你最好再閱讀該篇文章蜂奸,文章對(duì)序列化...
    jiangmo閱讀 456評(píng)論 0 2