java ->IO流_序列化流與反序列化流
序列化流與反序列化流
用於從流中讀取對象的操作流 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修飾。只要被transient或static修飾了,序列化時這個屬性就不會序列化了。
同時靜態修飾也不會被序列化,因為序列化是把對象數據進行持久化存儲,而靜態的屬於類加載時的數據,不會被序列化。
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流_序列化流與反序列化流