天天看點

了解Java對象序列化——Serializable接口

概述:當一個類實作了Serializable接口(該接口僅為标記接口,不包含任何方法定義),表示該類可以序列化.序列化的目的是将一個實作了Serializable接口的對象轉換成一個位元組序列,可以。

把該位元組序列儲存起來(例如:儲存在一個檔案裡),以後可以随時将該位元組序列恢複為原來的對象。甚至可以将該位元組序列放到其他計算機上或者通過網絡傳輸到其他計算機上恢複,隻要該計

算機平台存在相應的類就可以正常恢複為原來的對象。

實作:要序列化一個對象,先要建立某些OutputStream對象,然後将其封裝在一個ObjectOutputStream對象内,再調用writeObject()方法即可序列化一個對象;反序列化也類似。

import java.io.*;

public class Person implements Serializable {

private String userName;

private String password;

public Person(String userName, String password) {

this.userName = userName;

this.password = password;

}

public String toString() {

return "userName:" + userName + " password:" + password;

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

//序列化一個對象(存儲到一個檔案)

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));

oos.writeObject("Save a object:\n");

oos.writeObject(new Person("Bruce", "123456"));

oos.close();

//反序列化,将該對象恢複(存儲到一個檔案)

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));

String s = (String)ois.readObject();

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

System.out.println(s + p);

//序列化一個對象(存儲到位元組數組)

ByteArrayOutputStream baos = new ByteArrayOutputStream();

ObjectOutputStream oos2 = new ObjectOutputStream(baos);

oos2.writeObject("Save another object:\n");

oos2.writeObject(new Person("Phil", "654321"));

oos2.close();

//反序列化,将該對象恢複(存儲到位元組數組)

ObjectInputStream ois2 = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));

s = (String)ois2.readObject();

p = (Person)ois2.readObject();

//輸入如下資訊

Save a object:

userName:Bruce password:123456

Save another object:

userName:Phil password:654321

transient關鍵字:

自動序列化将對象的所有字段都持久化了,有時候需要對某些字段不進行自動化(如密碼,因為序列化會暴光密碼資訊),這個時候可以使用transient關鍵字(隻能和Serializable對象一起使

用),其作用是不序列化某些字段。将Person類的字段改為如下定義,再運作上面的程式:

private transient String password;

userName:Bruce password:null

userName:Phil password:null

控制序列化字段,甚至該字段是被transient修飾的字段也能将其序列化。手動序列化需要添加兩個私有(private)方法(writeObject()和readObject()),在該私有方法中控制序列花字段。

private void writeObject(ObjectOutputStream out) throws IOException {

out.defaultWriteObject(); //序列化所有非transient字段,必須是該方法的第一個操作

out.writeObject(password); //序列化transient字段

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {

in.defaultReadObject(); //反序列化所有非transient字段,必須是該方法的第一個操作

password = (String)in.readObject(); //反序列化transient字段

userName:David password:13579

控制序列化字段還可以使用Externalizable接口替代Serializable借口。此時需要定義一個預設構造器,否則将為得到一個異常(java.io.InvalidClassException: Person; Person; no

valid constructor);還需要定義兩個方法(writeExternal()和readExternal())來控制要序列化的字段。

public class Person implements Externalizable {

public Person() {

System.out.println("default constructor invoked!");

public void writeExternal(ObjectOutput out) throws IOException {

//序列化字段

out.writeObject(userName);

out.writeObject(password);

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

//反序列化字段

userName = (String)in.readObject();

password = (String)in.readObject();

oos.writeObject(new Person("Leo", "1984"));

default constructor invoked!

userName:Leo password:1984

以上方式隻能恢複成Java對象,如果想要恢複成其他對象(如C++對象),那就要将Java對象轉換為XML格式,這樣可以使其被各種平台和各種語言使用。可以使用随JDK一起釋出的javax.xam.*類庫,或者使用開源XOM類庫(可以從www.xom.nu下載下傳并獲得文檔)。