Java 序列化


title: Java 序列化
categories: 后臺開發(fā)
tags:

  • java
  • 基礎(chǔ)知識
  • 必備

Java 序列化

什么是序列化?為什么需要序列化

  • 序列化:將 Java 對象轉(zhuǎn)換成字節(jié)流的過程陌宿。
  • 反序列化:將字節(jié)流轉(zhuǎn)換成 Java 對象的過程。

當(dāng) Java 對象需要在網(wǎng)絡(luò)上傳輸 或者 持久化存儲到文件中時舶得,就需要對 Java 對象進行序列化處理弥虐。

注意事項:

  1. 某個類可以被序列化,則其子類也可以被序列化

  2. 聲明為 static 和 transient 的成員變量珠插,不能被序列化颖对。static 成員變量是描述類級別的屬性,transient 表示臨時數(shù)據(jù)

  3. 反序列化讀取序列化對象的順序要保持一致

Java 序列化方式有幾種缤底?

答案: 三種

1. 實現(xiàn) Serializable 接口(隱式序列化)

通過實現(xiàn) Serializable 接口,這種是隱式序列化(不需要手動)江解,這種是最簡單的序列化方式徙歼,會自動序列化所有非 static 和 transient 關(guān)鍵字修飾的成員變量。

Java 的序列化機制是通過在運行時判斷類的 serialVersionUID 來驗證版本一致性的魄梯。在進行反序列化時,JVM 會把傳來的字節(jié)流中的 serialVersionUID 與本地相應(yīng)實體(類)的 serialVersionUID 進行比較灭翔,如果相同就認為是一致的辣苏,可以進行反序列化哄褒,否則就會出現(xiàn)序列化版本不一致的異常狭园。

class Student implements Serializable{
    private String name;
    private int age;
    public static int QQ = 1234;
    private transient String address = "CHINA";
    
    Student(String name, int age ){
        this.name = name;
        this.age = age;
    }
    public String toString() {
        return "name: " + name + "\n"
                +"age: " + age + "\n"
                +"QQ: " + QQ + "\n" 
                + "address: " + address;
                
    }
    public void SetAge(int age) {
        this.age = age;
    }
}
public class SerializableDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //創(chuàng)建可序列化對象
        System.out.println("原來的對象:");
        Student stu = new Student("Ming", 16);
        System.out.println(stu);
        //創(chuàng)建序列化輸出流
        ByteArrayOutputStream buff = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(buff);
        //將序列化對象存入緩沖區(qū)
        out.writeObject(stu);
        //修改相關(guān)值
        Student.QQ = 6666; // 發(fā)現(xiàn)打印結(jié)果QQ的值被改變
        stu.SetAge(18);   //發(fā)現(xiàn)值沒有被改變
        //從緩沖區(qū)取回被序列化的對象
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buff.toByteArray()));
        Student newStu = (Student) in.readObject();
        System.out.println("序列化后取出的對象:");
        System.out.println(newStu);
    }
}
2.實現(xiàn) Externalizable 接口。(顯式序列化)**

Externalizable 接口繼承自 Serializable, 我們在實現(xiàn)該接口時罚舱,必須實現(xiàn)writeExternal()和readExternal()方法,而且只能通過手動進行序列化管闷,并且兩個方法是自動調(diào)用的窃肠,因此,這個序列化過程是可控的冤留,可以自己選擇哪些部分序列化。

public class Blip implements Externalizable{
    private int i ;
    private String s;
    public Blip() {}
    public Blip(String x, int a) {
        System.out.println("Blip (String x, int a)");
        s = x;
        i = a;
    }
    public String toString() {
        return s+i;
    }
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // TODO Auto-generated method stub
        System.out.println("Blip.writeExternal");
        out.writeObject(s);
        out.writeInt(i);
//      
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        // TODO Auto-generated method stub
        System.out.println("Blip.readExternal");
        s = (String)in.readObject();
        i = in.readInt();
    }
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        System.out.println("Constructing objects");
        Blip b = new Blip("A Stirng", 47);
        System.out.println(b);
        ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("F://Demo//file1.txt"));
        System.out.println("保存對象");
        o.writeObject(b);
        o.close();
        //獲得對象
        System.out.println("獲取對象");
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("F://Demo//file1.txt"));
        System.out.println("Recovering b");
        b = (Blip)in.readObject();
        System.out.println(b);
    }
 
}
3.實現(xiàn) Serializable 接口+添加 writeObject() 和 readObject() 方法。(顯+隱序列化)

如果想將方式一和方式二的優(yōu)點都用到的話泊窘,可以采用方式三, 先實現(xiàn) Serializable 接口瓜贾,并且添加writeObject()和readObject()方法携悯。注意這里是添加,不是重寫或者覆蓋憔鬼。但是添加的這兩個方法必須有相應(yīng)的格式。

  1. 方法必須要被 private 修飾 ----->才能被調(diào)用
  2. 第一行調(diào)用默認的 defaultRead/WriteObject(); ----->隱式序列化非static和transient
  3. 調(diào)用 read/writeObject() 將獲得的值賦給相應(yīng)的值 --->顯式序列化
public class SerDemo implements Serializable{
    public transient int age = 23;
    public String name ;
    public SerDemo(){
        System.out.println("默認構(gòu)造器咸灿。侮叮。悼瘾。");
    }
    public SerDemo(String name) {
        this.name = name;
    }
    private  void writeObject(ObjectOutputStream stream) throws IOException {
        stream.defaultWriteObject();
        stream.writeInt(age);
    }
    private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
        stream.defaultReadObject();
        age = stream.readInt();
    }
    
    public String toString() {
        return "年齡" + age + "  " + name; 
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SerDemo stu = new SerDemo("Ming");
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(stu);
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));
        SerDemo stu1 = (SerDemo) in.readObject();
        System.out.println(stu1);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卸勺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碍庵,老刑警劉巖悟狱,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異苹享,居然都是意外死亡浴麻,警方通過查閱死者的電腦和手機得问,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門宫纬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來或杠,“玉大人,你說我怎么就攤上這事向抢。” “怎么了叉信?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵艘希,是天一觀的道長。 經(jīng)常有香客問我覆享,道長,這世上最難降的妖魔是什么丑罪? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮跪另,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煤搜。我一直安慰自己,他們只是感情好擦盾,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布迹卢。 她就那樣靜靜地躺著,像睡著了一般婶希。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上彤枢,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天筒饰,我揣著相機與錄音,去河邊找鬼瓷们。 笑死,一個胖子當(dāng)著我的面吹牛碘裕,可吹牛的內(nèi)容都是我干的攒钳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼不撑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了姆坚?” 一聲冷哼從身側(cè)響起实愚,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烹俗,失蹤者是張志新(化名)和其女友劉穎萍程,沒想到半個月后兔仰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡忍法,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年榕吼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羹蚣。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡顽素,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胁出,到底是詐尸還是另有隱情,我是刑警寧澤全蝶,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布抑淫,位于F島的核電站,受9級特大地震影響始苇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜埂蕊,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一蓄氧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喉童,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至排抬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間番甩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工缘薛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卡睦,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓牺汤,卻偏偏與公主長得像浩嫌,于是被迫代替她去往敵國和親檐迟。 傳聞我的和親對象是個殘疾皇子码耐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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