2012-04-30 48 views
1

我有一個Java序列化的問題。假設我有一個Object持久化到文件系統。我們如何根據後一版本中的對象結構修改更新文件的結構?如何更新持久化Java對象的結構?

例如,如果我救對象

A{int a; String b} to file 

我改變了結構A{int a; String b, char c}有什麼辦法,我可以根據A的較新版本中改變先前保存的文件?

回答

2

這是可能的,你需要向後修改下一個版本,在Java序列化規範中解釋的方法如下:http://docs.oracle.com/javase/1.3/docs/guide/serialization/spec/version.doc.html

然而,這個問題是一個很好的例子,爲什麼使用本地Java序列化來長時間保存對象通常是一個很好的例子一個壞主意。如果您使用了特定的格式(XML,JSON或其他格式),您可以輕鬆讀取和轉換文件本身,或者可以通過不同的串行器實現讀取任何版本的文件,從而更輕鬆地從一個版本遷移到另一個。

+0

XML中的持久對象會顯着增加文件大小,但自然序列化確實有這種僵化......感謝您的幫助。這似乎不是一個平衡這兩個問題的簡單方法。 – Korben

1

是的(只要結構不是不同和obeys certain rules)。比方說,你的文件中包含的序列化表示:

class Foo 
{ 
    int a;      // value = 42 
    String b;      // value = "don't panic" 
} 

不過,現在已經更改了Foo對象,現在的類定義是:

class Foo 
{ 
    int a; 
    String b; 
    char c; 
} 

當你的文件讀取時,序列化機制會自動彈出Foo的實例存在,並將a設爲42和b爲「不要恐慌」。 c的值不在流中,所以默認情況下它被設置爲Java默認值(在這種情況下,對於字符0x0000)。

現在,你有你的目標,你可能會爲c設定值:

foo.c = 'Z'; 

如果你現在連載的對象,並將其寫入文件,該文件將具有的序列化表示:

class Foo 
{ 
    int a;      // value = 42 
    String b;      // value = "don't panic" 
    char c;      // value = 'Z' 
} 

正如我們上面看到的,c在對象流中沒有找到缺省值。您可能想要定義不同的默認值。序列化機制爲您在序列化/反序列化時執行自定義代碼提供了一種方法。有關詳細信息,請參閱Javadoc for Serializable(請參閱readObject()的說明)。


編輯:JB Nizet指出,有一個名爲serialVersionUID一個特殊的序列號區。您需要確保對象中的版本ID與對象流中的內容匹配。你可以在你的對象明確設置這樣的:

private static final long serialVersionUID = 1L; 

但是,如果你沒有原來指定它,它得到了寫出使用自動從田野和方法簽名的哈希算法生成的值。如果你需要重新生成這個數字(所以你可以將它定義爲你班級的一個常量,那麼你需要使用serialver工具

+0

不,它會導致一個異常,因爲新類的計算serialVersionUID將不會與上一個類生成的文件中存儲的那個相同。您需要將serialVersionUID靜態字段添加到新類,該類與前一個類具有相同的值。 –

+0

@JBNizet:確實需要定義'serialVersionUID'。讓我看看我不能在那裏工作...... –