1. 程式人生 > >java ->IO流_序列化流與反序列化流

java ->IO流_序列化流與反序列化流

set final found class文件 ati 技術分享 保存到文件 back 序列化對象

序列化流與反序列化流

用於從流中讀取對象的操作流 ObjectInputStream 稱為 反序列化流

用於向流中寫入對象的操作流 ObjectOutputStream 稱為 序列化流(對象保存到文件中)

l 特點:用於操作對象。可以將對象寫入到文件中,也可以從文件中讀取對象。

對象序列化流ObjectOutputStream

ObjectOutputStream 將 Java 對象的基本數據類型和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構)對象。通過在流中使用文件可以實現對象的持久存儲。

註意:只能將支持 java.io.Serializable

接口的對象寫入流中

技術分享圖片

技術分享圖片

l 代碼演示:

public class ObjectStreamDemo {

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

/*

* 將一個對象存儲到持久化(硬盤)的設備上。

*/

writeObj();//對象的序列化。

}

public static void writeObj() throws IOException {

//1,明確存儲對象的文件。

FileOutputStream fos = new FileOutputStream("tempfile\\obj.object");

//2,給操作文件對象加入寫入對象功能。

ObjectOutputStream oos = new ObjectOutputStream(fos);

//3,調用了寫入對象的方法。

oos.writeObject(new Person("wangcai",20));

//關閉資源。

oos.close();

}

}

l Person類

//只有實現了Serializable接口的類才可以被序列化

public class Person implements Serializable {

private String name;

private int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

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;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + "]";

}

}

對象反序列化流ObjectInputStream

ObjectInputStream 對以前使用 ObjectOutputStream 寫入的基本數據和對象進行反序列化。支持 java.io.Serializable接口的對象才能從流讀取。

技術分享圖片

技術分享圖片

l 代碼演示

public class ObjectStreamDemo {

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

readObj();//對象的反序列化。

}

public static void readObj() throws IOException, ClassNotFoundException {

//1,定義流對象關聯存儲了對象文件。

FileInputStream fis = new FileInputStream("tempfile\\obj.object");

//2,建立用於讀取對象的功能對象。

ObjectInputStream ois = new ObjectInputStream(fis);

  //3.向下轉型

Person obj = (Person)ois.readObject();

System.out.println(obj.toString());

}

}

序列化接口

當一個對象要能被序列化,這個對象所屬的類必須實現Serializable接口。否則會發生異常NotSerializableException異常。

同時當反序列化對象時,如果對象所屬的class文件在序列化之後進行的修改,那麽進行反序列化也會發生異常InvalidClassException。發生這個異常的原因如下:

l 該類的序列版本號與從流中讀取的類描述符的版本號不匹配

l 該類包含未知數據類型

l 該類沒有可訪問的無參數構造方法

Serializable標記接口。該接口給需要序列化的類,提供了一個序列版本號。serialVersionUID. 該版本號的目的在於驗證序列化的對象和對應類是否版本匹配。

l 代碼修改如下,修改後再次寫入對象,讀取對象測試

public class Person implements Serializable {

//給類顯示聲明一個序列版本號 ,只要設定了serivalVersionUID ,那麽該類在序列化和反序列化的時候就不會發生異常

private static final long serialVersionUID = 1L;

private String name;

private int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

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;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + "]";

}

}

瞬態關鍵字transient

當一個類的對象需要被序列化時,某些屬性不需要被序列化,這時不需要序列化的屬性可以使用關鍵字transient修飾。只要被transientstatic修飾了,序列化時這個屬性就不會序列化了。

同時靜態修飾也不會被序列化,因為序列化是把對象數據進行持久化存儲,而靜態的屬於類加載時的數據,不會被序列化。

l 代碼修改如下,修改後再次寫入對象,讀取對象測試

public class Person implements Serializable {

/*

* 給類顯示聲明一個序列版本號。

*/

private static final long serialVersionUID = 1L;

private static String name;

private transient/*瞬態*/ int age;

public Person() {

super();

}

public Person(String name, int age) {

super();

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;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + "]";

}

}

java ->IO流_序列化流與反序列化流