對象流

對象流

概念

用於存儲和讀取基本數據類型數據或對象的處理流,可以把Java中的對象寫入到數據源中,也能把對象從數據源中還原回來

  • 序列化:用ObjectOutputStream類保存基本數據類型或對象的機制
  • 反序列化:用ObjectInputStream類讀取基本類型數據

注意:ObjectOutputStream和ObjectInputStream不能序列化static和transient修飾的成員變量

  • transient的含義:不讓序列化這個屬性

對象的序列化機制

理解

對象序列化機制允許把內存中的Java對象轉換成平台無關的二進制流,從而允許把這種二進制流持久地保存在磁盤上,或通過網絡將這種二進制流傳輸到另一個網絡節點。當其它程序獲取了這種二進制流,就可以恢復成原來的Java對象

使用

一個可序列化的java對象需要滿足的要求

  1. 如果需要讓某個對象支持序列化機制,該類必須實現如下兩個接口之一,否則,會拋出NotSerializableException異常

    • Serializable(常用)
    • Externalizable
  2. 需要當前類提供一個全局常量serialVersionUID

    public static final long serialVersionUID = 4892322646L;

    其中數值沒有嚴格要求,隨便寫一個即可

  3. 內部所有屬性也必須是可序列化的(默認情況下,基本數據類型和String是可序列化的)

過程

序列化

  1. 創建一個ObjectOutputStream
  2. 調用 ObjectOutputStream 對象的 writeObject( 對象) 方法輸出可序列化對象
  3. 注意寫出一次,操作flush()方法

反序列化

  1. 創建一個 ObjectInputStream
  2. 調用 readObject() 方法讀取流中的對象

注意

如果某個類的屬性不是基本數據類型或 String 類型,而是另一個引用類型,那麼這個引用類型必須是可序列化的(實現Serializable接口),否則擁有該類型的Field 的類不能序列化

字符串序列化反序列化操作

序列化

使用ObjectOutputStream來實現

public void test1(){
//序列化過程:將內存中的java對象保存在磁盤中或通過網絡傳輸出去
    ObjectOutputStream oos = null;
    try {
        oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
        oos.writeObject(new String("我愛北京天安門"));
        oos.flush();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(oos != null)
                oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

反序列化

使用ObjectInputStream來實現

public void test2(){
//反序列化過程:將磁盤文件中對象還原為內存中的一個java對象
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(new FileInputStream("object.dat"));
        Object object = ois.readObject();
        String s = (String) object;
        System.out.println(s);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if(ois != null)
                ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

自定義類序列化反序列化操作

自定義類

注意自定義類一定要實現Serializable接口和有一個全局變量serialVersionUID

public class Person implements Serializable {

public static final long serialVersionUID = 4892322646L;

private String name;
private int age;

public Person() {
}

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

public String getName() {
    return name;
}

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

public int getAge() {
    return age;
}

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

序列化

public void test1(){
    //序列化過程:將內存中的java對象保存在磁盤中或通過網絡傳輸出去
    ObjectOutputStream oos = null;
    try {
        oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
        oos.writeObject(new String("我愛北京天安門"));
        oos.flush();

        oos.writeObject(new Person("殷志源",42));
        oos.flush();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(oos != null)
                oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

反序列化

public void test2(){
    //反序列化過程:將磁盤文件中對象還原為內存中的一個java對象
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(new FileInputStream("object.dat"));
        Object object = ois.readObject();
        String s = (String) object;

        Person p = (Person) ois.readObject();
        System.out.println(s);
        System.out.println(p);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if(ois != null)
                ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

oLGam.png

serialVersionUID的理解

相當於一個標識

目的是以序列化對象進行版本控制,有關各版本反序列化時是否兼容

如果對類進行了修改,但是定義了serialVersionUID,反序列化的時候依舊可以識別出其內容

如果類沒有顯示定義這個靜態常量,它的值是Java運行時環境根據類的內部細節自動生成的。若類的實例變量做了修改,serialVersionUID可能發生變化。所以需要顯示聲明

Tags: