前面寫了一個序列化的文章,這次重新整理一下。
1.Serialize概念
Java的對象序列化就是將那些實現了Serializable接口的對象轉換成一個字節序列。并能夠
在以后將這個字節完全恢復為原來的對象。
對象序列化的概念加入到語言當中就是為了支持兩種主要特性
一是Java的遠程方法調用(Remote Method Invocation, RMI)。當向遠程對象發送消息時,
需要通過序列化來傳輸參數和返回值。
二是Javabean對象序列化。有些服務器通過將所有的SESSION 數據(包括BEAN)寫入磁盤來支持任意長的SESSION生命期,即使服務器停機也不會丟失。當服務器重新啟動后,串行化的數據被恢復。同樣的理由,在重負載的站點上支持服務器分簇的環境中,許多服務器通過串行化來復制SESSION。如果你的BEAN不支持串行化,服務器就不能正確地保存和傳輸類。
只要對象實現了Serializable接口,對象的序列化處理就會非常簡單。
2.Serialize方法
要序列化一個對象,首先要創建某些OutputStream對象,然后將其封裝在一個ObjectOutputStream對象內。
這時,只需要調用writeObject()即可將對象序列化,并將其發送給OutputStream。反之,將一個序列化對象還原為一個對象,需要將一個InputStream封裝在ObjectInputStream內,然后調用readObject()。
OutputStream和InputStream常用的是ByteArrayOutputStream/FileOutputStream和ByteArrayInputStream/FileInputStream。
下面兩個類以ByteArray方式實現序列化:
public final class Serialization
{
/**
* Serialize the object into a byte array.
*/
public static byte[] serialize( Object obj )
throws IOException
{
ByteArrayOutputStream baos;
ObjectOutputStream oos;
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream( baos );
oos.writeObject( obj );
oos.close();
return baos.toByteArray();
}
/**
* Deserialize an object from a byte array
*/
public static Object deserialize( byte[] buf )
throws ClassNotFoundException, IOException
{
ByteArrayInputStream bais;
ObjectInputStream ois;
bais = new ByteArrayInputStream( buf );
ois = new ObjectInputStream( bais );
return ois.readObject();
}
}
public class DefaultSerializer
implements Serializer
{
public static final DefaultSerializer INSTANCE = new DefaultSerializer();
/**
* Construct a DefaultSerializer.
*/
public DefaultSerializer()
{
// no op
}
/**
* Serialize the content of an object into a byte array.
*
* @param obj Object to serialize
* @return a byte array representing the object's state
*/
public byte[] serialize( Object obj )
throws IOException
{
return Serialization.serialize( obj );
}
/**
* Deserialize the content of an object from a byte array.
*
* @param serialized Byte array representation of the object
* @return deserialized object
*/
public Object deserialize( byte[] serialized )
throws IOException
{
try {
return Serialization.deserialize( serialized );
} catch ( ClassNotFoundException except ) {
throw new WrappedRuntimeException( except );
}
}
}
File方式的序列化大致如下:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(out.txt));
out.writeObject(obj);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(out.txt));
Object obj = (Object)in.readObject();
in.close();
3.Serialize定制
缺省的序列化機制并不難操縱,如果有特殊的需求那又該怎么辦?例如,也許要考慮特殊的安全問題,而且
你不希望對象的某一部分被序列化;或者一個對象被還原后,某子對象需要重新創建,從而不需要將該子對象
序列化。在這樣的特殊情況下,可通過實現Externalizable接口來對序列化過程進行控制。這個Externalizable
接口繼承了Serializable接口,同時增加了兩個方法:writeExternal(ObjectOutput out)和readExternal(ObjectInput in)
Serializable對象完全以它存儲的二進制位為基礎來構造,而不用調用構造器。而對于一個Externalizable對象
缺省構造器都會被調用,然后調用readExternal()。下面列子中,如果Blip3()構造器注釋掉,程序會報錯:no valid constructor
// Reconstructing an externalizable object.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
import com.bruceeckel.simpletest.*;
import java.io.*;
import java.util.*;
public class Blip3 implements Externalizable {
private static Test monitor = new Test();
private int i;
private String s; // No initialization
public Blip3() {
System.out.println("Blip3 Constructor");
// s, i not initialized
}
public Blip3(String x, int a) {
System.out.println("Blip3(String x, int a)");
s = x;
i = a;
// s & i initialized only in nondefault constructor.
}
public String toString() { return s + i; }
public void writeExternal(ObjectOutput out)
throws IOException {
System.out.println("Blip3.writeExternal");
// You must do this:
out.writeObject(s);
out.writeInt(i);
}
public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException {
System.out.println("Blip3.readExternal");
// You must do this:
s = (String)in.readObject();
i = in.readInt();
}
public static void main(String[] args)
throws IOException, ClassNotFoundException {
System.out.println("Constructing objects:");
Blip3 b3 = new Blip3("A String ", 47);
System.out.println(b3);
ObjectOutputStream o = new ObjectOutputStream(
new FileOutputStream("Blip3.out"));
System.out.println("Saving object:");
o.writeObject(b3);
o.close();
// Now get it back:
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("Blip3.out"));
System.out.println("Recovering b3:");
b3 = (Blip3)in.readObject();
System.out.println(b3);
monitor.expect(new String[] {
"Constructing objects:",
"Blip3(String x, int a)",
"A String 47",
"Saving object:",
"Blip3.writeExternal",
"Recovering b3:",
"Blip3 Constructor",
"Blip3.readExternal",
"A String 47"
});
}
}