一、序列化
- 序列化定義:序列化是将對象狀态轉換為可保持或傳輸的格式的過程。與序列化相對的是反序列化,它将流轉換為對象。這兩個過程結合起來,可以輕松地存儲和傳輸資料。
- 目的:
- 以某種存儲形式使自定義對象持久化
- 将對象從一個地方傳遞到另一個地方
二、Java序列化
- 一個對象能夠序列化的前提是實作Serializable接口。Serializable接口沒有方法,更像是個标記。有了這個标記的Class就能被序列化機制處理。如下:
-
class myPoint implements Serializable{
}
- JAVA反序列化不會調用任何構造器
- 序列化的控制:Externalizable。讀寫都交給你
- 要在方法writeExternal寫入序列化的參數
- 要在方法readExternal讀取反序列化的值
- 要有預設的構造方法(readExternal執行完成,再執行預設的構造器)
-
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException,ClassNotFoundException;
public class Point implements Externalizable {
private int a;
private int b;
public Point(int a, int b) {
this.a = a;
this.b = b;
}
public Point() {
}
public String toString() {
return a + " , " + b;
}
public void writeExternal(ObjectOutput out) throws IOException {
out.write(a);
out.write(b);
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
a = in.read();
b = in.read();
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
String file = "d://1.txt";
Point p = new Point(1, 2);
System.out.println(p);
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p);
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Point pp = (Point) ois.readObject();
System.out.println(pp);
}
}
- transient關鍵字 關閉序列化自動進行。
- 不管你選擇了哪種序列化形式,都要為自己編寫的每個可序列化的類聲明一個顯示的序列版本UID(serial version UID)
三、序列化的問題
在effective java中列舉出了java序列化要注意的一些問題:
- 謹慎地設計實作Serializable接口
- 實作釋出了就是一種承諾
- 如果一個類是為繼承設計的,在‘允許子類實作Serializable接口’與‘禁止子類實作Serializable接口’取一個折中的方案是:提供一個可通路的無參構造器
- 保護性地編寫 readObject()方法,因為readObject()是建構執行個體的入口。
- 不保護可能出現 建構了不滿足要求的 執行個體
- 考慮自定義的序列化形式
- 邏輯内容 與 實體表示法
- 如果一個對象的 ‘實體表示法’等同于它的‘邏輯内容’,可能就适用于使用預設的序列化形式。
- 如果有更好的 ‘實體表示法’在表示‘邏輯内容’則可以自定義序列化形式。
-
public class StringList implements Serializable {
private transient int size = 0;
private transient Entity head = null;
public final void add(String str) {
// ...
}
private static class Entity {
String data;
Entity next;
Entity previous;
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.write(size);
for (Entity e = head; e != null; e = e.next) {
s.writeObject(e.data);
}
}
private void readObject(ObjectInputStream s) throws IOException,
ClassNotFoundException {
s.defaultReadObject();
int num = s.read();
for (int i = 0; i < num; i++) {
this.add((String) s.readObject());
}
}
}
四、序列化代理模式
序列化機制提供的鈎子函數有:
writeReplace writeObject readObject readResolve
- writeReplace:序列化的時候替換所要序列化的對象。
- writeObject:寫入序列化的對象
- readObject:讀取序列化的對象
- readResolve:最後傳回序列化對象
-
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Date;
public final class Period implements Serializable {
private static final long serialVersionUID = 100L;
private final Date start;
private final Date end;
public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0) {
throw new IllegalArgumentException(start + " after " + end);
}
}
public Date start() {
return new Date(start.getTime());
}
public Date end() {
return new Date(end.getTime());
}
public String toString() {
return start + " - " + end;
}
// 不給
private Object writeReplace() {
return new SerializationProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("proxy request");
}
private static class SerializationProxy implements Serializable {
private final Date start;
private final Date end;
SerializationProxy(Period p) {
this.start = p.start;
this.end = p.end;
}
private Object readResolve() {
return new Period(start, end);
}
private static final long serialVersionUID = 1000L;
}
}
五、序列化算法
- 将對象執行個體相關的類中繼資料輸出。
- 遞歸地輸出類的超類描述直到不再有超類。
- 類中繼資料完了以後,開始從最頂層的超類開始輸出對象執行個體的實際資料值。
- 從上至下遞歸輸出執行個體的資料
- 具體參考,講得很詳細的:http://longdick.javaeye.com/blog/458557
六、參考文獻
- javatips's blog,The Java serialization algorithm revealed: http://www.javaworld.com/community/node/2915
- Blog ,Java 序列化算法透析:http://longdick.javaeye.com/blog/458557
- Java Object Serialization Specification:http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf
- java程式設計思想 http://www.bookfm.com/reader/online.html?bookid=123482&page=1