Java基礎(chǔ)鞏固-關(guān)于Java序列化和反序列化

題外話:
從事IT要學(xué)習(xí)的東西太多了,有時(shí)候會(huì)比較浮躁,因?yàn)橐獙W(xué)的東西太多但又無(wú)從下手,甚至有很多基礎(chǔ)都還沒(méi)有深入學(xué)習(xí),這個(gè)時(shí)候應(yīng)當(dāng)靜下心來(lái),正所謂不忘初心,方能始終,之前一直聽(tīng)說(shuō)過(guò)序列化,但也沒(méi)有去深入一點(diǎn)點(diǎn)的了解過(guò),這個(gè)時(shí)候,就當(dāng)好好鞏固下了~

java序列化

常被稱為持久化,將其寫入磁盤中。
對(duì)于一個(gè)存在于jvm的對(duì)象來(lái)說(shuō),內(nèi)部的狀態(tài)保存在內(nèi)存中,當(dāng)jvm停止時(shí)這些狀態(tài)就丟失了,但有些時(shí)候?qū)ο蟮膬?nèi)部是需要持久保存的,對(duì)象序列化機(jī)制(object serialization)是Java語(yǔ)言內(nèi)建的一種對(duì)象持久化方式,可以很容易的在JVM中的活動(dòng)對(duì)象和字節(jié)數(shù)組(流)之間進(jìn)行轉(zhuǎn)換,該機(jī)制中對(duì)象可以表示為字節(jié)序列,該字節(jié)序列包括該對(duì)象的數(shù)據(jù),有關(guān)對(duì)象的類型的信息和存儲(chǔ)在對(duì)象中數(shù)據(jù)的類型。

數(shù)據(jù)序列化就是將對(duì)象或者數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化成特定的格式,使其可在網(wǎng)絡(luò)中傳輸,或者可存儲(chǔ)在內(nèi)存或者文件中。反序列化則是相反的操作,將對(duì)象從序列化數(shù)據(jù)中還原出來(lái)。而對(duì)象序列化后的數(shù)據(jù)格式可以是二進(jìn)制,可以是XML,也可以是JSON等任何格式。

【整個(gè)過(guò)程在jvm獨(dú)立的,在一個(gè)平臺(tái)上序列化的對(duì)象可以在另外的平臺(tái)反序列化】

java類序列化的條件:

1.該類必須實(shí)現(xiàn) java.io.Serializable接口。
2.該類的所有屬性必須是可序列化的。如果有一個(gè)屬性不是可序列化的,則該屬性必須注明是短暫的。如果你想知道一個(gè) Java 標(biāo)準(zhǔn)類是否是可序列化的,請(qǐng)查看該類的文檔。檢驗(yàn)一個(gè)類的實(shí)例是否能序列化十分簡(jiǎn)單, 只需要查看該類有沒(méi)有實(shí)現(xiàn) java.io.Serializable接口。

為什么序列化

1.將結(jié)構(gòu)化的對(duì)象變?yōu)闊o(wú)結(jié)構(gòu)的字節(jié)流,存儲(chǔ)對(duì)象在存儲(chǔ)介質(zhì)中,方便下次使用可以快捷獲取,便于數(shù)據(jù)傳輸。
2.序列化的過(guò)程通俗講,就是一個(gè)“freeze”的過(guò)程,它將一個(gè)對(duì)象freeze住,然后進(jìn)行存儲(chǔ),等到再次需要的時(shí)候,再將這個(gè)對(duì)象de-freeze就可以立即使用。

jdk內(nèi)置序列化

java對(duì)序列化提供了很好的支持,當(dāng)一個(gè)對(duì)象實(shí)現(xiàn)了Serilizable接口,這個(gè)對(duì)象就可以被序列化,我們不關(guān)心其內(nèi)在的原理,只需要了解這個(gè)類實(shí)現(xiàn)了Serilizable接口,這個(gè)類的所有屬性和方法都會(huì)自動(dòng)序列化。可以說(shuō)Serilizable只是一個(gè)標(biāo)識(shí),實(shí)際的序列化和反序列化工作是通過(guò)java.io.ObjectOuputStream和java.io.ObjectInputStream來(lái)完成的。ObjectOutputStream的writeObject方法可以把一個(gè)Java對(duì)象寫入到流中,ObjectInputStream的readObject方法可以從流中讀取一個(gè)Java對(duì)象。

transient關(guān)鍵字

在實(shí)際開(kāi)發(fā)過(guò)程中可能遇到說(shuō)一個(gè)對(duì)象中的屬性有些需要序列化有些則不用,比如說(shuō)一個(gè)用戶有些敏感信息(密碼,銀行卡號(hào)),為了安全考慮不需要在網(wǎng)絡(luò)操作中被傳輸。
這種時(shí)候使用transient可以使對(duì)應(yīng)的屬性不被寫入磁盤持久化。換句話說(shuō),這個(gè)對(duì)象的生命周期僅存在調(diào)用者的內(nèi)存中而不被持久化在硬盤中或者網(wǎng)絡(luò)傳輸。

//使用例子
package serializable;
import java.io.*;

public class TransientTest implements Serializable{
    static class UserInfo implements Serializable {
        private String name; //此處加static反序列化后仍能取到是因?yàn)閟tatic修飾的變量存在jvm內(nèi)存中
        private transient String psw;//transient 只能修飾變量(屬性)
        public UserInfo(String name, String psw) {
            this.name = name;
            this.psw = psw;
        }

        public String toString() {
            return "name=" + name + ", psw=" + psw;
        }
    }

    public static void main(String[] args) {
        UserInfo userInfo = new UserInfo("張三", "123456");
        System.out.println(userInfo);
        try {
            // 序列化將對(duì)象屬性寫入到UserInfo.txt文件中,被設(shè)置為transient的屬性沒(méi)有被序列
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
            o.writeObject(userInfo);
            o.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            // 重新讀取序列化內(nèi)容
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
            UserInfo readUserInfo = (UserInfo) in.readObject();
            System.out.println(readUserInfo.toString()); //修飾transient關(guān)鍵字的屬性打印為null
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
測(cè)試

Externalizable接口

在java中,對(duì)象的序列化可以通過(guò)兩種接口實(shí)現(xiàn),除了Serilizable接口,還有就是Externalizable接口。
1.若實(shí)現(xiàn)Serializable,則所有序列化將會(huì)自動(dòng)執(zhí)行。
2.若實(shí)現(xiàn)Externalizable,序列化的過(guò)程需手動(dòng)執(zhí)行,需要在writeExternal方法中進(jìn)行手工指定所要序列化的變量,與是否被transient修飾無(wú)關(guān)。

import java.io.*;
/**
 * Created by LJW on 2018/5/28.
 * Externalizable接口測(cè)試
 */
public class TestExternalizable implements Externalizable {
    private transient String content = "就算被transient修飾,但如果實(shí)現(xiàn)的是Externalizable接口,我還是可能被序列化";
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    }

    public static void main(String[] args) throws Exception {
        TestExternalizable et = new TestExternalizable();
        //將TestExternalizable序列化到test.txt文件中
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                new File("test.txt")));
        out.writeObject(et);
        //反序列化test.txt中的信息
        ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                "test.txt")));
        et = (TestExternalizable) in.readObject();
        System.out.println(et.content);//成功打印content內(nèi)容而不是null,說(shuō)明反序列化有取到被transient修飾的變量屬性
        out.close();
        in.close();
    }
}

serialVersionUID

在查看jdk源碼的時(shí)候,經(jīng)常看到這種代碼

private static final long serialVersionUID = 2877471301981509474L; //xxxL 

一個(gè)類如果使用了java.io.Serializable接口,在序列化到文件時(shí)會(huì)自動(dòng)生成一個(gè)serialVersionUID,用于對(duì)類進(jìn)行版本控制(通過(guò)判斷實(shí)體類的serialVersionUID來(lái)驗(yàn)證版本一致性的。在進(jìn)行反序列化時(shí),JVM會(huì)把傳來(lái)的字節(jié)流中的serialVersionUID與本地相應(yīng)實(shí)體類的serialVersionUID進(jìn)行比較,如果相同就認(rèn)為是一致的,可以進(jìn)行反序列化,否則就會(huì)出現(xiàn)序列化版本不一致InvalidCalssException的異常)

如何生成

Intellij IDEA可以自動(dòng)為serializable的類生成一個(gè)serialVersionUID。

File->Preferences->Inspections->Serializationissues,將其展開(kāi)后將serialzable class without "serialVersionUID"打上勾;
之后雙擊下class類名 ALT+ENTER即可生成隨機(jī)的serialVersionUID

生成serialVersionUID

總結(jié)

  1. Java序列化就是把對(duì)象轉(zhuǎn)換成字節(jié)序列,而Java反序列化就是把字節(jié)序列還原成Java對(duì)象,在java中可以通過(guò)實(shí)現(xiàn)Serializable和Externalizable兩種接口實(shí)現(xiàn)序列化。
  2. 采用Java序列化與反序列化技術(shù),一是可以實(shí)現(xiàn)數(shù)據(jù)的持久化,在MVC模式中很有用;二是可以對(duì)象數(shù)據(jù)的遠(yuǎn)程通信,序列化用于通信,服務(wù)端把數(shù)據(jù)序列化發(fā)送到客戶端。客戶端收到數(shù)據(jù)反序列化對(duì)數(shù)據(jù)操作。
  3. 序列化的好處:通過(guò)序列化可以把數(shù)據(jù)永久保存在硬盤上(通常放在文件里)
  4. transient關(guān)鍵字只能修飾屬性,被transient修飾的屬性將不會(huì)被序列化(這邊的前提是實(shí)現(xiàn)Serializable接口,還有需注意被static修飾的屬性也無(wú)法被序列化,static修飾的變量存在jvm內(nèi)存中,如果反序列化后得到static修飾的屬性,是從jvm取而不是反序列化后得到)。
  5. serialVersionUID主要用于反序列化的時(shí)候驗(yàn)證版本的一致性,常在jdk,各種jar包中使用。
最后編輯于
?著作權(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閱讀 230,527評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,687評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 178,640評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,957評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,682評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 56,011評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 43,183評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,714評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,435評(píng)論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,665評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,838評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,251評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,588評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,379評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,627評(píng)論 2 380

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