(PS:本文爲做者原著,如需轉載,請註明出處-_^) java
使用java以來,序列化隨處可見,至於爲何要用序列化、序列化能解決什麼問題,做爲一個普通的碼農,通常不怎麼會去深刻研究,因爲最近在看mina和公司內部涉及到nio框架的一些源碼,裏面涉及到hession、java這兩種序列化,至於hession序列化爲何會誕生以及在apache項目中使用如此普遍,以及java自己序列化存在哪些缺陷,甚是不解,爲了解答上面拋出來的疑惑,以及進一步瞭解java的序列化機制,這裏開個小頭,從java的序列化接口Serializable開始提及apache
jdk包裏的Serializable接口的註釋主要說明了如下幾點:數組
1.類經過實現Serializable接口來啓用序列化,不然該類的任何狀態將沒法被序列化,同時也沒法用於反序列化框架
2.若繼承的父類沒有實現Serializable接口,可是又想讓子類可序列化,有三個注意事項:jvm
a).子類實現Serializable接口測試
b).子類必須有可訪問的無參構造方法,用於保存和恢復父類的public或protected或同包下的package字段的狀態,不然在序列化或反序列化時會拋出RuntimeException異常spa
c).對於序列化後的子類,在進行反序列化時,理論上沒法初始化父類中private(不可訪問)對象變量的狀態或值
操作系統
3.在對可序列化類中的屬性進行序列化時,若是遇到不可序列化的對象變量,此時會針對不可序列化的類拋出NotSerializableException異常code
4.對於可序列化的非數組類,強烈建議顯示聲明static型、long型、final型serialVersionUID字段用於標識當前序列化類的版本號,不然在跨操做系統、跨編譯器之間進行序列化和反序列化時容易出現InvalidClassException異常orm
5.對於可序列化類中的static、transient對象變量,在序列化時沒法保存其狀態或值,static對象變量在反序列化時取得的值爲當前jvm中對應類中對應static變量的值,而transient(瞬態)關鍵字則通常用於標識那些在序列化時不須要傳遞的狀態變量
簡單的測試代碼:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * 序列化測試 * * @author sume * */ public class SerializableImpl implements Serializable { private static final long serialVersionUID = -6433786313435044319L; static String staticVal = "static1"; transient String transientVal = "transient1"; String val = "val1"; /** * main */ public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { // 序列化 SerializableImpl sila1 = new SerializableImpl(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("Serializable.txt")); objectOutputStream.writeObject(sila1); objectOutputStream.close(); // 反序列化 SerializableImpl.staticVal = "static2"; ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("Serializable.txt")); SerializableImpl sila2 = (SerializableImpl) objectInputStream.readObject(); objectInputStream.close(); // 比較各個屬性的值 System.out.println(sila2.staticVal); System.out.println(sila2.transientVal); System.out.println(sila2.val); } }輸出結果:
static2 null val1
從輸出結果能夠看出:
1.反序列化後類中static型變量staticVal的值爲當前jvm中對應static變量的值,爲:static2,而不是序列化時的值:static1
2.transient關鍵字標識的變量的狀態並無在序列化中被保存,所以反序列化後
transientVal變量的值爲null
3.第三個爲常見的對象狀態在序列化和反序列化過程當中的傳遞
簡單印證了前面所說的幾點內容
另外:對於在序列化和反序列化過程當中須要對類進行特殊處理或須要指定替代對象的操做,
本文沒有涉及到,會在後面進一步討論時給出