(十二)對象的序列化和反序列化


1恨统、基本介紹

1.對象的序列化:將Object類型的對象轉(zhuǎn)換成byte序列挺益,簡單來講就是要存儲對象,將對象寫入文件卵酪。
序列化流(ObjectOutputStream),核心方法writeObject()

2.對象的反序列化:將byte序列轉(zhuǎn)換成Object類型的對象,簡單來講就是從文件中讀取對象凛澎。
反序列化流(ObjectInputStream)霹肝,核心方法readObject()

3.序列化接口:對象必須實現(xiàn)序列化接口(Serializable),才能進(jìn)行序列化塑煎,否則將出現(xiàn)異常沫换。該接口中沒有任何方法,只是一個標(biāo)準(zhǔn)最铁。

注意:

當(dāng)一個類實現(xiàn)了序列化接口讯赏,其子類都可以實現(xiàn)序列化;

對子類對象實現(xiàn)反序列化操作時冷尉,如果其父類沒有實現(xiàn)序列化接口漱挎,那么其父類的構(gòu)造方法會被調(diào)用,不會進(jìn)行反序列化雀哨。


2磕谅、實現(xiàn)對象的序列化——寫入對象

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

// 創(chuàng)建Student類并實現(xiàn)Serializable接口,準(zhǔn)備將該類的對象寫入文件
class Student implements Serializable {
    private String name;
    private int age;

    public Student() {

    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class Demo1 {

    public static void main(String[] args) throws IOException {

        fun1();
    }

    public static void fun1() throws IOException {

        /*
         * 根據(jù)其構(gòu)造方法 
         * ObjectOutputStream(OutputStream out) 
         * 傳入的參數(shù)是OutputStream類型的
         * 因為多態(tài)的存在 
         * 所以O(shè)utputStream類的子類類型都可以
         */

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f:\\Demo1.txt"));
        Student s1 = new Person("Tom", 20);
        oos.writeObject(s1);
        oos.close();
    }

}


3雾棺、實現(xiàn)對象的反序列化——讀取對象

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Demo2 {

    public static void main(String[] args) throws ClassNotFoundException, IOException {

        fun2();
    }

    public static void fun2() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f:\\Demo1.txt"));
        // 直接向下強(qiáng)制轉(zhuǎn)型為Student類

        /*
         * 注意readObject()方法會拋出兩個異常:
         * IOException,ClassNotFoundException
         * 之所以會有ClassNotFoundException 
         * 是因為對象是依賴于其所屬類的字節(jié)碼文件(類名.class)的
         * 因此在讀取對象時膊夹,
         * 必須要求其所屬類的字節(jié)碼文件也存在
         */

        Student obj = (Student) ois.readObject();
        System.out.println(obj.getName() + "," + obj.getAge());
        ois.close();
    }
}


4、Serializable接口

1.序列號:

在寫入對象時捌浩,對象所屬的類實現(xiàn)的Serializable接口會在該類內(nèi)部同時寫入一個唯一的UID序列號放刨,以便找到該類;如果在寫入對象完成之后尸饺,修改了該類中的任意內(nèi)容进统,那么序列號也會隨之改變柿估,會導(dǎo)致找不到該類策州,從而引發(fā)異常。因此在處理對象的序列化時窿给,建議聲明自己的UID馋辈,例如:

static final long serialVersionUID = 42L; 

這樣不論該類內(nèi)部怎樣發(fā)生變化抚芦,都不會改變序列號。

2.transient:

例如對象在網(wǎng)絡(luò)中傳輸也需要實現(xiàn)序列化迈螟,但如果希望某個元素不在網(wǎng)絡(luò)中傳輸以節(jié)省流量叉抡,即不參與默認(rèn)的序列化過程,可將其修飾為:

private transient int age;

這樣Student類對象的年齡屬性就不會被存儲答毫,從而實現(xiàn)了不參與序列化褥民,最終返回的是該屬性的默認(rèn)值。
  但不參與虛擬機(jī)默認(rèn)的序列化不代表不能被序列化洗搂,可以手動實現(xiàn)參與序列化過程消返,將readObject()方法和writeObject()方法的方法簽名添加到對應(yīng)類中载弄,代碼如下:

class Student implements Serializable {
    private String name;//可以默認(rèn)進(jìn)行序列化
    private transient int age;//需要手動實現(xiàn)序列化

    public Student() {

    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    //添加writeObject()的方法簽名
     private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{
         s.defaultWriteObject();//將可以默認(rèn)實現(xiàn)序列化的元素進(jìn)行序列化操作
         s.writeObject(age);//手動實現(xiàn)age的序列化
     }

    //添加readObject()的方法簽名
     private void readObject(java.io.ObjectInputStream s)throws java.io.IOException,ClassNotFoundException{
          s.defaultReadObject();//將可以默認(rèn)實現(xiàn)反序列化的元素進(jìn)行反序列化操作
          this.age = (int) s.readObject();//手動實現(xiàn)age的反序列化操作
    }
}

實現(xiàn)手動控制某些元素是否參與序列化過程,目的是為了提高程序運(yùn)行的性能撵颊,可以參考ArrayList的原碼宇攻,在其定義的數(shù)組上修飾了transient,并不是不進(jìn)行序列化倡勇,而是手動實現(xiàn)對有效數(shù)據(jù)進(jìn)行序列化逞刷,反序列化同理,因此提高了程序的性能妻熊。


版權(quán)聲明:歡迎轉(zhuǎn)載夸浅,歡迎擴(kuò)散,但轉(zhuǎn)載時請標(biāo)明作者以及原文出處扔役,謝謝合作帆喇!             ↓↓↓
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亿胸,隨后出現(xiàn)的幾起案子坯钦,更是在濱河造成了極大的恐慌,老刑警劉巖损敷,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葫笼,死亡現(xiàn)場離奇詭異深啤,居然都是意外死亡拗馒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門溯街,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诱桂,“玉大人,你說我怎么就攤上這事呈昔』拥龋” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵堤尾,是天一觀的道長肝劲。 經(jīng)常有香客問我,道長郭宝,這世上最難降的妖魔是什么辞槐? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮粘室,結(jié)果婚禮上榄檬,老公的妹妹穿的比我還像新娘。我一直安慰自己衔统,他們只是感情好鹿榜,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布海雪。 她就那樣靜靜地躺著,像睡著了一般舱殿。 火紅的嫁衣襯著肌膚如雪奥裸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天沪袭,我揣著相機(jī)與錄音刺彩,去河邊找鬼。 笑死枝恋,一個胖子當(dāng)著我的面吹牛创倔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播焚碌,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼畦攘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了十电?” 一聲冷哼從身側(cè)響起知押,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鹃骂,沒想到半個月后台盯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡畏线,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年静盅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寝殴。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒿叠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蚣常,到底是詐尸還是另有隱情市咽,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布抵蚊,位于F島的核電站施绎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贞绳。R本人自食惡果不足惜谷醉,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望熔酷。 院中可真熱鬧孤紧,春花似錦、人聲如沸拒秘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至押蚤,卻和暖如春蔑歌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背揽碘。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工次屠, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雳刺。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓劫灶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親掖桦。 傳聞我的和親對象是個殘疾皇子本昏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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