1. 程式人生 > >47、序列化和反序列化

47、序列化和反序列化

在工作中有可能遇到多臺機器遠端通訊的情況,如果要將機器A中的某個java物件傳輸到機器B上面,需要將這個java物件轉換為位元組序列然後進行傳輸。將物件轉換為位元組序列的過程叫做序列化,反之叫做反序列化。

一個物件如果支援序列化,需要實現Serializable的介面,這個介面中沒有任何方法,實現該介面後,JVM會給這個物件做特殊待遇

將java物件儲存到硬盤裡面

使用序列化還可以將一個物件儲存到硬碟中,然後再通過反序列化將該物件讀取到記憶體裡面。

建立一個Student類,實現Serializable介面

package com.monkey1024.serializable;

import java.io.Serializable; public class Student implements Serializable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }

使用ObjectOutputStream將Student物件寫出到硬碟中

package com.monkey1024.serializable;

import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; /** * 將Student物件序列化到硬碟中 * */ public class ObjectOutput { public static void main(String[] args) { Student s = new Student(); s.setName("張三");
// 建立輸出流(序列化流) try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("zhangsan"));) { //將物件寫出到硬碟中 oos.writeObject(s); oos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

使用ObjectInputStream將硬碟中的物件讀取到記憶體中

package com.monkey1024.serializable;

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

/**
 * 從硬碟中讀取Student物件
 *
 */
public class ObjectInput {

    public static void main(String[] args) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("zhangsan"));) {
            Student s = (Student)ois.readObject();
            System.out.println(s.getName());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

序列化版本號

在一個類實現Serializable介面後,系統會給每個物件一個序列化版本號,當這個類的原始碼被修改後,系統會重新分配一個新的序列化版本號,這樣做的好處就是保證序列化和反序列化的物件內容一致。例如將一個物件序列化到硬碟之後,修改這個物件所對應類的原始碼,在進行反序列化是就會報出InvalidClassException異常。如果手動編寫序列化版本號之後,就不會出現這個異常了。

package com.monkey1024.serializable;

import java.io.Serializable;

public class Student implements Serializable {

    /**
     * 自動生成序列化版本號
     */
    private static final long serialVersionUID = -716323668524282676L;

    private String name;
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

transient關鍵字

如果不希望將Student類中的age屬性序列化,可以使用transient宣告該屬性,在序列化時將忽略這個屬性。

package com.monkey1024.serializable;

import java.io.Serializable;

public class Student implements Serializable {

    /**
     * 自動生成序列化版本號
     */
    private static final long serialVersionUID = -716323668524282676L;

    private String name;

    //age不序列化
    transient private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}