IO流(3) - 序列化和反序列化

TigerJin發表於2021-09-09

物件的序列化/反序列化

物件序列化,就是將Object轉換成byte序列,反之叫做物件的反序列化。

序列化流(ObjectOutputStream),是一個過濾流 --> writeObject,

反序列化流(ObjectInputStream) --> readObject.

序列化介面(Serializable)

物件必須實現序列化介面才能進行序列化,否則將出現NoSerializableException異常。此介面沒有任何方法,只是一個標準。

建立一個Person.java實體類:

public class Person implements Serializable {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

寫一個物件流測試類:

public class ObjectTest {
    public static void main(String[] args) throws IOException {
        String file = "F:\Code\JavaSE\obj.txt";
        // 物件序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        Person student = new Person("張三", 22);
        oos.writeObject(student);
        oos.flush();
        oos.close();

        try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
            Person per = (Person) ois.readObject();
            System.out.println(per);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

輸出結果:

Person{name='張三', age=22}

在進行物件序列化操作時,並不希望所有的變數都進行序列化操作,這時可以在變數前加上transient關鍵字,使得該變數不進行序列化操作,並不是說不做JVM預設的序列化就不能序列化了,也可以自己完成這個變數的序列化。

Person.java中給age變數前面加上transient關鍵字,新增以下兩種方法:

private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
    s.defaultWriteObject(); //把JVM能預設序列化的元素進行序列化操作
    s.writeObject(age); //被transient修飾的變數,自己完成序列化操作
}

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
    s.defaultReadObject(); //把JVM能預設反序列化的元素進行反序列化操作
    this.age = (Integer) s.readObject();//自己完成age的反序列化操作
}

加上這兩個方法後,即使變數前有transient關鍵字修飾,也可以進行序列化/反序列化操作。

分析ArrayList原始碼中序列化和反序列化的問題

序列化中,子類和父類之間的呼叫:一個類實現了序列化介面,繼承它的子類都能夠進行序列化操作。

序列化顯式建立物件,需要遞迴呼叫父類方法。

對子類物件進行反序列化操作時,如果其父類沒有實現序列化介面,那麼其父類的建構函式會被呼叫。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2144/viewspace-2797088/,如需轉載,請註明出處,否則將追究法律責任。

相關文章