java之IO流(序列化流與反序列化流)
一.物件序列化流ObjectOutputStream
用於向流中寫入物件的操作流 ObjectOutputStream 稱為 序列化流
ObjectOutputStream 將 Java 物件的基本資料型別和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構)物件。通過在流中使用檔案可以實現物件的持久儲存。
注意:只能將支援 java.io.Serializable 介面的物件寫入流中
構造方法摘要:
ObjectOutputStream(OutputStream out):建立寫入指定OutputStream的ObjectOutputStream。
方法摘要:
writeObject(Object obj):將指定的物件寫入ObjectOutputStream。
//Person類 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 + "]"; } }
//測試類 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(); } }
二.物件反序列化流ObjectInputStream
ObjectInputStream 對以前使用 ObjectOutputStream 寫入的基本資料和物件進行反序列化。支援 java.io.Serializable介面的物件才能從流讀取
構造方法摘要:
ObjectInputStream(InputStream in):建立從指定InputStream讀取的ObjectInputStream。
方法摘要:
readObject(Object obj):從ObjectInputStream讀取物件
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); Person obj = (Person)ois.readObject(); System.out.println(obj.toString()); } }
三.序列化介面
當一個物件要能被序列化,這個物件所屬的類必須實現Serializable介面。否則會發生異常NotSerializableException異常。同時當反序列化物件時,如果物件所屬的class檔案在序列化之後進行的修改,那麼進行反序列化也會發生異常InvalidClassException。
原因:
1.該類的序列版本號與從流中讀取的類描述符的版本號不匹配
2.該類包含未知資料型別
3.該類沒有可訪問的無引數構造方法
Serializable標記介面。該介面給需要序列化的類,提供了一個序列版本號。serialVersionUID. 該版本號的目的在於驗證序列化的物件和對應類是否版本匹配。
public class Person implements Serializable { //給類顯示宣告一個序列版本號。 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修飾了,序列化時這個屬性就不會序列化了。同時靜態修飾也不會被序列化,因為序列化是把物件資料進行持久化儲存,而靜態的屬於類載入時的資料,不會被序列化。
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 + "]"; } }