控制序列化就是有選擇的序列化對象,而不是把對象的所以內容都序列化,控制對象序列化和反序列方法,可以在序列化過程中儲存其他非this對象包含的數據 。java.io.Externalizable 。繼承自了java.io.Serializable 。
java.io.Externalizable的所有實現者必須提供讀取和寫出的實現。
java.io.Externalizable接口(自己實現):
voidreadExternal(ObjectInput in) 反序列時被調用
void writeExternal(ObjectOutput out) 序列化時被調用
import java.io.*;
import java.util.*; //本程序通過實現Externalizable接口控制對象序列化和反序列
public class UserInfo implements Externalizable {
public String userName;
public String userPass;
public int userAge;
public UserInfo(){
}
public UserInfo(String username,String userpass,int userage){
this.userName=username;
this.userPass=userpass;
this.userAge=userage;
}
//當序列化對象時,該方法自動調用
public void writeExternal(ObjectOutput out) throws IOException{
System.out.println("現在執行序列化方法");
//可以在序列化時寫非自身的變量
Date d=new Date();
out.writeObject(d);
//只序列化userName,userPass變量
out.writeObject(userName);
out.writeObject(userPass);
}
//當反序列化對象時,該方法自動調用
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{
System.out.println("現在執行反序列化方法");
Date d=(Date)in.readObject();
System.out.println(d);
this.userName=(String)in.readObject();
this.userPass=(String)in.readObject();
}
public String toString(){
return "用戶名: "+this.userName+";密碼:"+this.userPass+";年齡:"+this.userAge;
}
}
import java.io.*; import java.util.*; //本程序通過實現Externalizable接口控制對象序列化和反序列
public class UserInfo implements Externalizable {
public String userName;
public String userPass;
public int userAge;
public UserInfo(){ }
public UserInfo(String username,String userpass,int userage){
this.userName=username;
this.userPass=userpass;
this.userAge=userage;
}
//當序列化對象時,該方法自動調用
public void writeExternal(ObjectOutput out) throws IOException{
System.out.println("現在執行序列化方法"); //可以在序列化時寫非自身的變量
Date d=new Date();
out.writeObject(d);
//只序列化userName,userPass變量
out.writeObject(userName);
out.writeObject(userPass);
}
//當反序列化對象時,該方法自動調用
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{
System.out.println("現在執行反序列化方法");
Date d=(Date)in.readObject();
System.out.println(d);
this.userName=(String)in.readObject();
this.userPass=(String)in.readObject();
}
public String toString(){
return "用戶名: "+this.userName+";密碼:"+this.userPass+ ";年齡:"+this.userAge;
}
}
改寫測試類 Java代碼
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.lang.management.*;
public class Test {
//序列化對象到文件
public static void serialize(String fileName){
try{
//創建一個對象輸出流,講對象輸出到文件
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));
UserInfo user=new UserInfo("renyanwei","888888",20);
out.writeObject(user); //序列化一個會員對象
out.close();
}catch (Exception x){
System.out.println(x.toString());
}
}
//從文件反序列化到對象
public static void deserialize(String fileName){
try{
//創建一個對象輸入流,從文件讀取對象
ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));
//讀取UserInfo對象並調用它的toString()方法
UserInfo user=(UserInfo)(in.readObject());
System.out.println(user.toString());
in.close();
}catch (Exception x){
System.out.println(x.toString());
}
}
public static void main(String[] args) {
serialize("D://test.txt");
System.out.println("序列化完畢");
deserialize("D://test.txt");
System.out.println("反序列化完畢");
}
}
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.lang.management.*;
public class Test {
//序列化對象到文件
public static void serialize(String fileName){
try {
//創建一個對象輸出流,講對象輸出到文件
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));
UserInfo user=new UserInfo("renyanwei","888888",20);
out.writeObject(user);
//序列化一個會員對象
out.close();
} catch (Exception x) {
System.out.println(x.toString());
}
}
//從文件反序列化到對象
public static void deserialize(String fileName){
try {
//創建一個對象輸入流,從文件讀取對象
ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));
//讀取UserInfo對象並調用它的toString()方法
UserInfo user=(UserInfo)(in.readObject());
System.out.println(user.toString()); in.close();
} catch (Exception x) {
System.out.println(x.toString());
}
}
public static void main(String[] args) {
serialize("D://test.txt");
System.out.println("序列化完畢");
deserialize("D://test.txt");
System.out.println("反序列化完畢");
}
}
序列化會自動存儲必要的信息,用以反序列化被存儲的實例,而外部化則只保存被存儲的類的標識。當你通過java.io.Serializable接口序列化一個對象時,有關類的信息,比如它的屬性和這些屬性的類型,都與實例數據一起被存儲起來。在選擇走Externalizable這條路時,Java 只存儲有關每個被存儲類型的非常少的信息。
每個接口的優點和缺點
Serializable接口
? 優點:內建支持
? 優點:易於實現
? 缺點:占用空間過大
? 缺點:由於額外的開銷導致速度變比較慢
Externalizable接口
? 優點:開銷較少(程序員決定存儲什么)
? 優點:可能的速度提升
? 缺點:虛擬機不提供任何幫助,也就是說所有的工作都落到了開發人員的肩上。
在兩者之間如何選擇要根據應用程序的需求來定。Serializable通常是最簡單的解決方案,但是它可能會導致出現不可接受的性能問題或空間問題;在出現這些問題的情況下,Externalizable可能是一條可行之路。
要記住一點,如果一個類是可外部化的(Externalizable),那么Externalizable方法將被用於序列化類的實例,即使這個類型提供了Serializable方法:
private void writeObject()
private void readObject()
被Serializable接口聲明的類的對象的內容都將被序列化,如果現在用戶希望自己指定序列化的內容,則可以讓一個類實現Externalizable接口,此接口定義如下:
Externalizable接口是Serializable接口的子接口,在此接口中定義了兩個方法,這兩個方法的作用如下。
writeExternal(ObjectOutput out):在此方法中指定要保存的屬性信息,對象序列化時調用。
readExternal(ObjectInput in):在此方法中讀取被保存的信息,對象反序列化時調用。
這兩個方法的參數類型是ObjectOutput和ObjectInput,兩個接口的定義如下。
ObjectOutput接口定義:
ObjectInput接口定義:
可以發現以上兩個接口分別繼承DataOutput和DataInput,這樣在這兩個方法中就可以像DataOutputStream和DataInputStream那樣直接輸出和讀取各種類型的數據。
如果一個類要使用Externalizable實現序列化時,在此類中必須存在一個無參構造方法,因為在反序列化時會默認調用無參構造實例化對象,如果沒有此無參構造,則運行時將會出現異常,這一點的實現機制與Serializable接口是不同的。
范例:修改Person類並實現Externalizable接口
以上程序中的Person類實現了Externalizable接口,這樣用戶就可以在類中有選擇地保存需要的屬性或者其他的具體數據。在本程序中,為了與之前的程序統一,將全部屬性保存下來。
范例:序列化和反序列化Person對象
從以上代碼中可以發現,使用Externalizable接口實現序列化明顯要比使用Serializable接口實現序列化麻煩得多,除此之外,兩者的實現還有不同,如表12-27所示。
表12-27
序 |
區 |
Serializable |
Externalizable |
1 |
實現復雜度 |
實現簡單,Java對其 有內建支持 |
實現復雜, 由開發人員自己完成 |
2 |
執行效率 |
所有對象由Java統一保存, 性能較低 |
開發人員決定哪個對象保存, 可能造成速度提升 |
3 |
保存信息 |
保存時占用空間大 |
部分存儲, 可能造成空間減少 |
在一般的開發中,因為Serializable接口的使用較為方便,所以出現較多
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。