1.定義:
序列化,也叫串行化--将對象寫到一個輸出流(一般是一個檔案)中。反序列化則是從一個輸入流中讀取一個對象。類中的成員必須是可序列化的,而且要實作Serializable接口,這樣的類的對象才能被序列化和反序列化。這個接口是一個表示型的接口。serialVersionUID 是一個串行化類的通用标示符,反串行化就是使用這個标示符確定一個加載的類對應一個可串行化的對象。
若自己指定了serialVersionUID,就可以在序列化後,去添加一個字段,或者方法,而不會影響到後期的還原,還原後的對象照樣可以使用,而且還多了方法可以用。serialVersionUID的生成,可以寫1,也可以寫2,但最好還是按照摘要算法,生成一個惟一的指紋數字,eclipse可以自動生成的,jdk也自帶了這個工具。一般寫法類似于
private static final long serialVersionUID = -763618247875550322L;
簡單的使用請參加我的另一篇習作:http://blog.csdn.net/gnuhpc/archive/2009/08/01/4396149.aspx
2.序列化步驟:
1)建立一個對象輸出流:可以包裝一個其他類型的輸出流。 2)通過對象輸出流的writeObject()寫對象。注意使用類型轉化,轉換為相應的類的對象。
3.反序列化步驟:
1)建立一個對象輸入流:可以包裝一個其他類型的輸出流。 2)通過對象輸出流的readObject()寫對象。
4.什麼對象需要被序列化?
序列化的基本想法是完成對執行個體資訊的保證。因為執行個體資訊在運作結束後就消失了。要儲存什麼資訊呢?一定不是關于方法的資訊。
5.使用注意事項:
a.有些屬性處于安全考慮不能被序列化(或者不能被序列化,比如Thread),則用transit修飾,若想進一步控制序列化和反序列化,則類中提供readObject()方法和writeObject()方法,(反)序列化時就會調用自定義的方法。注意這兩個方法不是在java.io.Serializable接口定義的,而是在ObjectInputStream和ObjectOutputStream類中定義的,這兩個類實作ObjectInput 和ObjectOutput兩個接口。下邊是一個可變數組的例子,取自Java in a Nutshell 2rd Edition,它在串行化實作了高效的針對可變數組程度調整的方法:
b.由于串行化是針對類的執行個體,也就是對象的,是以static這樣的成員是類相關的,也就不會被串行化。
c.注意,API中一個類一旦被串行化了,那麼它的父類都是串行化的。你自己設計的類要是想被串行化,那麼其父類要確定都串行化。父類一旦串行化,則子類們都自動實作了串行化。是以内部類和可擴充類不建議串行化。
d. 若想加密序列化的資料,可以重寫writeObject和readObject,并将加密算法寫入其中,最後調用stream.defaultWriteObject();或者stream.defaultReadObject();實作模糊化——當然,你若是想在序列化和反序列化前後執行任何操作都可以在這裡定制,比如,這個類的父類實作了串行化,但你并不希望這個類可以被串行化,那麼就可以在串行化和反串行化的時候抛出異常:
如果需要對整個對象進行加密和簽名,最簡單的是将它放在一個 javax.crypto.SealedObject 和/或 java.security.SignedObject 包裝器中。兩者都是可序列化的,是以将對象包裝在 SealedObject 中可以圍繞原對象建立一種 “包裝盒”。必須有對稱密鑰才能解密,而且密鑰必須單獨管理。同樣,也可以将 SignedObject 用于資料驗證,并且對稱密鑰也必須單獨管理。
e.序列化不是針對的對象的檔案和方法,而是對象的狀态,是以在反序列化時對象的類檔案必須存在。
f.若想建立自己的串行化方式請實作Externalizable接口,而不是Serializable接口,重寫下邊兩個方法:
public void writeExternal(ObjectOutput out) throws IOException;
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
注意這裡你沒有了預設的動作可以做,一切都要靠自己。除此之外這個接口與串行化接口沒有差別。預設的串行化方法可能會帶來時間開銷,若你想優化的話,不妨從自定義簡單串行化方法開始。這個接口的實際用途在于若你想串行化父類的資料成員,那麼依靠原始的串行化接口是無法滿足的,你必須自定義串行化方法:
import java.io.*;
public class TestExternalizable
{
FileOutputStream fout = null;
ObjectOutputStream objOut = null;
public TestExternalizable() {
try{
TestSub testSub = new TestSub();
testSub.setName(NAME);
testSub.setAge(AGE);
fout = new FileOutputStream(FILE_NAME);
objOut = new ObjectOutputStream(fout);
objOut.writeObject(testSub);
objOut.flush();
objOut.close();
fout.close();
FileInputStream fin = new FileInputStream(FILE_NAME);
ObjectInputStream objIn = new ObjectInputStream(fin);
TestSub ts = (TestSub)objIn.readObject();
objIn.close();
fin.close();
System.out.println(ts.name+" "+ts.age);
} catch(Exception ex) {
ex.printStackTrace();
}
public static void main(String[] args)
new TestExternalizable();
class TestSuper{
String name = null;
int age = 0;
public void setName(String name) {
this.name = name;
public void setAge(int age) {
this.age = age;
public void readExternal(ObjectInput objectInput) {
try{
name = (String)objectInput.readObject();
age = objectInput.readInt();
} catch(Exception ex) {
}
public void writeExternal(ObjectOutput objectOutput) {
try
{
objectOutput.writeObject(name);
objectOutput.writeInt(age);
} catch (Exception ex) {
class TestSub extends TestSuper implements Externalizable {
public TestSub() {
import java.io.*; public class TestExternalizable { FileOutputStream fout = null; ObjectOutputStream objOut = null; public TestExternalizable() { try{ TestSub testSub = new TestSub(); testSub.setName(NAME); testSub.setAge(AGE); fout = new FileOutputStream(FILE_NAME); objOut = new ObjectOutputStream(fout); objOut.writeObject(testSub); objOut.flush(); objOut.close(); fout.close(); FileInputStream fin = new FileInputStream(FILE_NAME); ObjectInputStream objIn = new ObjectInputStream(fin); TestSub ts = (TestSub)objIn.readObject(); objIn.close(); fin.close(); System.out.println(ts.name+" "+ts.age); } catch(Exception ex) { ex.printStackTrace(); } } public static void main(String[] args) { new TestExternalizable(); } } class TestSuper{ String name = null; int age = 0; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void readExternal(ObjectInput objectInput) { try{ name = (String)objectInput.readObject(); age = objectInput.readInt(); } catch(Exception ex) { ex.printStackTrace(); } } public void writeExternal(ObjectOutput objectOutput) { try { objectOutput.writeObject(name); objectOutput.writeInt(age); } catch (Exception ex) { ex.printStackTrace(); } } } class TestSub extends TestSuper implements Externalizable { public TestSub() { } }
h.你若是在一個打開的流中寫了兩次,第二次是不會被儲存的,若想重新寫要調用<code>ObjectOutputStream.reset()</code> 方法。