Java基礎之Serializable

1、概念

序列化是Java提供的用于保存對象狀態(tài)的機制枪汪,可以將內(nèi)存中各種對象的狀態(tài)(實例變量)保存下來怀愧,并且將保存的對象狀態(tài)再讀出來。

2挫酿、何時需要序列化

  • 當需要將內(nèi)存中對象的狀態(tài)保存到文件中或數(shù)據(jù)庫中時构眯,可以進行序列化;
  • 當需要使用套接字在網(wǎng)絡上傳輸對象的時候早龟,可以進行序列化惫霸;
  • 當需要通過RMI傳輸對象的時候,可以進行序列化葱弟;

3壹店、序列化方式

在Java中通過socket傳輸數(shù)據(jù)時,數(shù)據(jù)類型可以有很多種芝加。常見的做法有兩種:一是把對象包裝成JSON字符串傳輸硅卢,二是采用java對象的序列化和反序列化。

4藏杖、如何實現(xiàn)序列化

需要實現(xiàn)序列化的類可以通過實現(xiàn) java.io.Serializable 接口以啟用其序列化功能将塑,未實現(xiàn)此接口的類將無法使其任何狀態(tài)序列化或反序列化≈剖校可序列化類的所有子類型本身都是可序列化的。序列化接口沒有方法或字段弊予,僅用于標識可序列化的語義祥楣。在反序列化過程中,將使用該類的公用或受保護的無參數(shù)構造方法初始化不可序列化類的字段∥笸剩可序列化的子類必須能夠訪問無參數(shù)的構造方法责鳍。可序列化子類的字段將從該流中還原兽间。

5历葛、serialVersionUID

Java的序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時嘀略,JVM會把傳來的字節(jié)流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較恤溶,如果相同就認為是一致的,可以進行反序列化帜羊,否則就會出現(xiàn)序列化版本不一致的異常咒程。serialVersionUID 用來表明類的不同版本間的兼容性。有兩種生成方式:

  • 一個是默認的1L讼育,比如:private static final long serialVersionUID = 1L帐姻;
  • 一個是根據(jù)類名、接口名奶段、成員方法及屬性等來生成一個64位的哈希字段饥瓷,比如: private static final long serialVersionUID = xxxxL;

6、序列化與反序列化

當兩個進程在進行遠程通信時痹籍,彼此可以發(fā)送各種類型的數(shù)據(jù)呢铆。無論是何種類型的數(shù)據(jù),都會以二進制序列的形式在網(wǎng)絡上傳送词裤。發(fā)送方需要把這個Java對象轉(zhuǎn)換為字節(jié)序列刺洒,才能在網(wǎng)絡上傳送;接收方則需要把字節(jié)序列再恢復為Java對象吼砂。

  • 把Java對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化逆航。
  • 把字節(jié)序列恢復為Java對象的過程稱為對象的反序列化。

對象的序列化主要有兩種用途:(1)把對象的字節(jié)序列永久地保存到硬盤上渔肩,通常存放在一個文件中因俐; (2)在網(wǎng)絡上傳送對象的字節(jié)序列;
java.io.ObjectOutputStream代表對象輸出流周偎,它的writeObject(Object obj)方法可對參數(shù)指定的obj對象進行序列化抹剩,把得到的字節(jié)序列寫到一個目標輸出流中。 java.io.ObjectInputStream代表對象輸入流蓉坎,它的readObject()方法從一個源輸入流中讀取字節(jié)序列澳眷,再把它們反序列化為一個對象,并將其返回蛉艾。
只有實現(xiàn)了Serializable和Externalizable接口的類的對象才能被序列化钳踊。Externalizable接口繼承自Serializable接口衷敌,實現(xiàn)Externalizable接口的類完全由自身來控制序列化的行為,而僅實現(xiàn)Serializable接口的類可以采用默認的序列化方式 拓瞪。
凡是實現(xiàn)Serializable接口的類都有一個表示序列化版本標識符的靜態(tài)變量:private static final long serialVersionUID;
序列化運行時使用一個稱為 serialVersionUID 的版本號與每個可序列化類相關聯(lián)缴罗,該序列號在反序列化過程中用于驗證序列化對象的發(fā)送者和接收者是否為該對象加載了與序列化兼容的類。如果接收者加載的該對象的類的 serialVersionUID 與對應的發(fā)送者的類的版本號不同祭埂,則反序列化將會導致 InvalidClassException面氓。可序列化類可以通過聲明名為serialVersionUID的字段(該字段必須是靜態(tài) (static)蛆橡、最終 (final) 的 long 型字段)顯式聲明其自己的 serialVersionUID:

7舌界、序列化機制

序列化分為兩大部分:序列化和反序列化。序列化是這個過程的第一部分航罗,將數(shù)據(jù)分解成字節(jié)流禀横,以便存儲在文件中或在網(wǎng)絡上傳輸。反序列化就是打開字節(jié)流并重構對象粥血。對象序列化不僅要將基本數(shù)據(jù)類型轉(zhuǎn)換成字節(jié)表示柏锄,有時還要恢復數(shù)據(jù)「纯鳎恢復數(shù)據(jù)要求有恢復數(shù)據(jù)的對象實例趾娃。ObjectOutputStream中的序列化過程與字節(jié)流連接,包括對象類型和版本信 息缔御。反序列化時抬闷,JVM用頭信息生成對象實例,然后將對象字節(jié)流中的數(shù)據(jù)復制到對象數(shù)據(jù)成員中耕突。ava.io包有兩個序列化對象的類笤成。ObjectOutputStream負責將對象寫入字節(jié)流,ObjectInputStream從字節(jié)流重構對象眷茁。序列化時炕泳,類的所有數(shù)據(jù)成員應可序列化除了聲明為transient或static的成員。將變量聲明為transient告訴JVM我們會負責將變元序列 化上祈。將數(shù)據(jù)成員聲明為transient后培遵,序列化過程就無法將其加進對象字節(jié)流中,沒有從transient數(shù)據(jù)成員發(fā)送的數(shù)據(jù)登刺。后面數(shù)據(jù)反序列化時籽腕, 要重建數(shù)據(jù)成員(因為它是類定義的一部分),但不包含任何數(shù)據(jù)纸俭,因為這個數(shù)據(jù)成員不向流中寫入任何數(shù)據(jù)皇耗。記住,對象流不序列化static或 transient揍很。我們的類要用writeObject()與readObject()方法以處理這些數(shù)據(jù)成員郎楼。使用writeObject()與 readObject()方法時矾瘾,還要注意按寫入的順序讀取這些數(shù)據(jù)成員。

8箭启、序列化的完全定制

如果一個類要完全負責自己的序列化,則實現(xiàn)Externalizable接口而不是Serializable接口蛉迹。Externalizable接口定義包 括兩個方法writeExternal()與readExternal()傅寡。利用這些方法可以控制對象數(shù)據(jù)成員如何寫入字節(jié)流.類實現(xiàn) Externalizable時,頭寫入對象流中北救,然后類完全負責序列化和恢復數(shù)據(jù)成員荐操,除了頭以外,根本沒有自動序列化珍策。這里要注意了托启。聲明類實現(xiàn) Externalizable接口會有重大的安全風險。writeExternal()與readExternal()方法聲明為public攘宙,惡意類可 以用這些方法讀取和寫入對象數(shù)據(jù)屯耸。如果對象包含敏感信息,則要格外小心蹭劈。這包括使用安全套接或加密整個字節(jié)流疗绣。

9、注意事項

  • 序列化時铺韧,只對對象的狀態(tài)進行保存多矮,而不管對象的方法;
  • 當一個父類實現(xiàn)序列化哈打,子類自動實現(xiàn)序列化塔逃,不需要顯式實現(xiàn)Serializable接口;
  • 當一個對象的實例變量引用其他對象料仗,序列化該對象時也把引用對象進行序列化湾盗;
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市罢维,隨后出現(xiàn)的幾起案子淹仑,更是在濱河造成了極大的恐慌,老刑警劉巖肺孵,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匀借,死亡現(xiàn)場離奇詭異,居然都是意外死亡平窘,警方通過查閱死者的電腦和手機吓肋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瑰艘,“玉大人是鬼,你說我怎么就攤上這事肤舞。” “怎么了均蜜?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵李剖,是天一觀的道長。 經(jīng)常有香客問我囤耳,道長篙顺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任充择,我火速辦了婚禮德玫,結果婚禮上,老公的妹妹穿的比我還像新娘椎麦。我一直安慰自己宰僧,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布观挎。 她就那樣靜靜地躺著琴儿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘁捷。 梳的紋絲不亂的頭發(fā)上凤类,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音普气,去河邊找鬼谜疤。 笑死,一個胖子當著我的面吹牛现诀,可吹牛的內(nèi)容都是我干的夷磕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼仔沿,長吁一口氣:“原來是場噩夢啊……” “哼坐桩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起封锉,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绵跷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后成福,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碾局,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年奴艾,在試婚紗的時候發(fā)現(xiàn)自己被綠了净当。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖像啼,靈堂內(nèi)的尸體忽然破棺而出俘闯,到底是詐尸還是另有隱情,我是刑警寧澤忽冻,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布真朗,位于F島的核電站,受9級特大地震影響僧诚,放射性物質(zhì)發(fā)生泄漏蜜猾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一振诬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衍菱,春花似錦赶么、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至琼锋,卻和暖如春放闺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缕坎。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工怖侦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谜叹。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓匾寝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荷腊。 傳聞我的和親對象是個殘疾皇子艳悔,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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