1. 程式人生 > >Serializable序列化與反序列化編碼例項

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(); 
System.out.println(s + p); 


//輸入如下資訊 
Save a object: 
userName:Bruce  password:123456 
Save another object: 
userName:Phil  password:654321 

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

用),其作用是不序列化某些欄位。將Person類的欄位改為如下定義,再執行上面的程式: 
private String userName; 
private transient String password; 
//輸入如下資訊 
Save a object: 
userName:Bruce  password:null 
Save another object: 
userName:Phil  password:null 

控制序列化欄位,甚至該欄位是被transient修飾的欄位也能將其序列化。手動序列化需要新增兩個私有(private)方法(writeObject()和readObject()),在該私有方法中控制序列花欄位。 
import java.io.*; 

public class Person implements Serializable { 
private String userName; 
private transient String password; 

public Person(String userName, String password) { 
this.userName = userName; 
this.password = password; 


public String toString() { 
return "userName:" + userName + "  password:" + password; 


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欄位 


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); 


//輸入如下資訊 
Save a object: 
userName:David  password:13579 

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

valid constructor);還需要定義兩個方法(writeExternal()和readExternal())來控制要序列化的欄位。 
import java.io.*; 

public class Person implements Externalizable { 
private String userName; 
private String password; 

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


public Person(String userName, String password) { 
this.userName = userName; 
this.password = password; 


public String toString() { 
return "userName:" + userName + "  password:" + password; 


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(); 


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("Leo", "1984")); 
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); 


//輸入如下資訊 
default constructor invoked! 
Save a object: 
userName:Leo  password:1984