Java-serializable序列化
序列化和反序列化的概念
把物件轉換為位元組序列的過程稱為物件的 序列化 —— ObjectOutputStream
把位元組序列恢復為物件的過程稱為物件的 反序列化 —— ObjectInputStream
java.io.ObjectOutputStream代表物件輸出流,它的writeObject(Objectobj)方法可對引數指定的obj物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。
java.io.ObjectInputStream代表物件輸入流,它的readObject()方法從一個源輸入流中讀取位元組序列,再把它們反序列化為一個物件,並將其返回。
物件的序列化主要有兩種用途
1) 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;
2) 在網路上傳送物件的位元組序列。
只有實現了 Serializable 和 Externalizable 介面的類的物件才能被序列化。
Externalizable介面繼承自Serializable介面,實現Externalizable介面的類完全由自身來控制序列化的行為,而僅實現Serializable介面的類可以採用預設的序列化方式 。
物件序列化包括如下步驟
1) 建立一個物件輸出流,它可以包裝一個其他型別的目標輸出流,如檔案輸出流;
2) 通過物件輸出流的writeObject()方法寫物件。
物件反序列化的步驟如下
1) 建立一個物件輸入流,它可以包裝一個其他型別的源輸入流,如檔案輸入流;
2) 通過物件輸入流的readObject()方法讀取物件。
例子
Person類
import java.io.Serializable;
/**
* <p>ClassName: Person<p>
* <p>Description:測試物件序列化和反序列化<p>
* @author xudp
* @version 1.0 V
* @createTime 2014-6-9 下午02:33:25
*/
public class Person implements Serializable {
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private String name;
private String sex;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
}
序列化和反序列化Person類物件
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;
/**
* <p>ClassName: TestObjSerializeAndDeserialize<p>
* <p>Description: 測試物件的序列化和反序列<p>
*/
public class TestObjSerializeAndDeserialize {
/**
* MethodName: SerializePerson
* Description: 序列化Person物件
* @throws FileNotFoundException
* @throws IOException
*/
private static void SerializePerson() throws FileNotFoundException,
IOException {
Person person = new Person();
person.setName("CR7");
person.setAge(33);
person.setSex("男");
// ObjectOutputStream 物件輸出流,將Person物件儲存到E盤的Person.txt檔案中,完成對Person物件的序列化操作
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
new File("E:/Person.obj")));
// 序列化
oo.writeObject(person);
System.out.println("Person物件序列化成功!");
oo.close();
}
/**
* MethodName: DeserializePerson
* Description: 反序列Perons物件
* @return
* @throws Exception
* @throws IOException
*/
private static Person DeserializePerson() throws Exception, IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("E:/Person.obj")));
// 反序列化
Person person = (Person) ois.readObject();
System.out.println("Person物件反序列化成功!");
return person;
}
public static void main(String[] args) throws Exception {
// 序列化Person物件,呼叫函式
SerializePerson();
// 反序列Perons物件,呼叫函式
Person p = DeserializePerson();
// 格式化輸出
System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
p.getName(), p.getAge(), p.getSex()));
}
}
SerialVersionUID
serialVersionUID的取值是Java執行時環境根據類的內部細節自動生成的。如果對類的原始碼作了修改,再重新編譯,新生成的類檔案的serialVersionUID的取值有可能也會發生變化。
類的serialVersionUID的預設值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的
serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。
顯式地定義serialVersionUID有兩種用途
1、 在某些場合,希望類的不同版本對序列化相容,因此需要確保類的不同版本具有相同的serialVersionUID;
2、 在某些場合,不希望類的不同版本對序列化相容,因此需要確保類的不同版本具有不同的serialVersionUID。