Java-IO流系列-物件流
物件流
物件流的介紹
-
ObjectInputStream和OjbectOutputSteam
-
用於儲存和讀取基本資料型別資料或物件的處理流。它的強大之處就是可以把Java中的物件寫入到資料來源中,也能把物件從資料來源中還原回來。
-
序列化:用ObjectOutputStream類儲存基本型別資料或物件的機制
-
反序列化:用ObjectInputStream類讀取基本型別資料或物件的機制
-
ObjectOutputStream和ObjectlnputStream不能序列化static和transient修飾的成員變數
-
凡是實現Serializable介面的類都有一個表示序列化版本識別符號的靜態變數:
- private static final long serialVersionUID;
- serialVersionUID用來表明類的不同版本間的相容性。簡言之,其目的是以序列化物件進行版本控制,有關各版本反序列化時是否相容。
- 如果類沒有顯示定義這個靜態變數,它的值是Java執行時環境根據類的內部細節自動生成的。若類的例項變數做了修改,serialVersionUID 可能發生變化。故建議,顯式宣告。
-
簡單來說,Java的序列化 機制是通過在執行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的位元組流中的serialVersionUID與木地相應實體類的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異
常。(InvalidCastException)
物件的序列化機制
-
物件序列化機制允許把記憶體中的Java物件轉換成平臺無關的:二進位制流,從而允許把這種二進位制流持久地儲存在磁碟上,或通過網路將這種二進位制流傳輸到另一個網路節點。當其它程式獲取了這種二進位制流,就可以恢復成原來的Java物件
-
序列化的好處在於可將任何實現了Serializable介面的物件轉化為位元組資料,使其在儲存和傳輸時可被還原
-
序列化是RMI ( Remote Method Invoke -遠端方法呼叫)過程的引數和返回值都必須實現的機制,而RMI是JavaEE的基礎。因此序列化機制是JavaEE平臺的基礎
-
如果需要讓某個物件支援序列化機制,則必須讓:物件所屬的類及其屬性是可序列化的,為了讓某個類是可序列化的,該類必須實現如下兩個介面之一。否則,會丟擲NotSerializableException異常
樣例
序列化過程
序列化過程:將記憶體中的java物件儲存到磁碟中或通過網路傳輸出去使用0bjectoutputstream實現
package com.dreamcold.io;
import java.io.*;
public class Demo18 {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("object.dat"));
oos.writeObject(new String("dreamcold"));
oos.flush();
oos.close();
}
}
反序列化過程
package com.dreamcold.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Demo19 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.dat"));
Object obj=ois.readObject();
String str=(String)obj;
System.out.println(str);
ois.close();
}
}
效果:
自定義物件序列化
Main.java
package com.dreamcold.io;
import java.io.*;
public class Demo18 {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("object.dat"));
Person person=new Person("dreamcold",21);
oos.writeObject(person);
oos.flush();
oos.close();
}
}
Person.java
package com.dreamcold.io;
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
執行結果
要讓物件可以被序列化要讓物件的類實現對應的Serializable介面,Serializable介面是標識介面
Person需要滿足如下的要求,方可序列化
- 需要實現介面: Serializable
- 當前類提供一個全域性常量: serialversionUId
- ,除了當前Person類需要實現Serializable介面之外, 還必須保證其內部所有屬性也必須是可序列化的。(預設我們的基本資料是可以序列化的)
package com.dreamcold.io;
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private Integer age;
public static final long serialVersionUID = -6849794470754662210L;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
讀取:
package com.dreamcold.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Demo19 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.dat"));
Object obj=ois.readObject();
Person person=(Person)obj;
System.out.println(person);
ois.close();
}
}
效果: