我有一個類用於不可變的使用,因此我想標記所有字段final
。序列化和不可變的對象
但是,該類被序列化並反序列化以通過網絡發送。爲了這個工作,需要一個空的構造函數。這可以防止我創建最終字段。
我敢肯定這是一個相當普遍的問題,但我找不到解決方案。我應該如何繼續?
我有一個類用於不可變的使用,因此我想標記所有字段final
。序列化和不可變的對象
但是,該類被序列化並反序列化以通過網絡發送。爲了這個工作,需要一個空的構造函數。這可以防止我創建最終字段。
我敢肯定這是一個相當普遍的問題,但我找不到解決方案。我應該如何繼續?
在典型的序列化情況下,並不要求類有一個空的構造函數或非final字段可序列化。
現在,如果你必須做你自己的序列化,或者你需要繼承一個沒有實現Serializable的類,那是不同的故事。
所以你需要提供一些你如何解決問題的更多細節。
不需要無參數構造函數。最派生的不可序列化類確實需要一個無參數構造函數,可用於最不派生的可序列化類。
如果您需要對readObject
內的字段進行變異,請使用通過readResolve
和writeReplace
的串行代理。
此問題是open bug on the Java language。 (請注意,這僅適用於必須手動執行序列化的情況,例如使用readObject)
從評估:「該問題適用於除類的可序列化字段以外的最終實例字段」,所以在標準情況下它工作正常。尼克似乎在做一些不同的事情。 – Yishai 2009-11-02 19:30:18
啊是的,我應該添加一個免責聲明,這隻適用於如果你必須鉤入readObject或類似的東西。 – 2009-11-02 19:38:08
要回應上述內容,如果正在執行java.io.Serializable
接口的路由,則不需要無參數構造函數。例如,看一下java.lang.Integer
源代碼,例如一個簡單的可序列化/不可變類,它有兩個構造函數:一個接受一個int,另一個接受一個String。源代碼:http://www.docjar.com/html/api/java/lang/Integer.java.html。 Javadoc:http://java.sun.com/javase/6/docs/api/java/lang/Integer.html。
同樣取決於你班級的複雜程度和你在做什麼,你可以考慮通過java.io.Externalizable
接口實現序列化(儘管有些人認爲它過時了,並且它需要一個無參數構造函數)。以下是關於SO的概述:What is the difference between Serializable and Externalizable in Java?,以下是官方的Java教程:http://java.sun.com/docs/books/tutorial/javabeans/persistence/index.html。
爲了記錄在案,因爲我有一個類似的問題:
我有一個消息「java.io.InvalidClassException:com.example.stuff.FooBar; com.example.stuff.FooBar;沒有有效的構造」
我認爲這是因爲它缺少默認的構造函數。但上面的答案確認它不是強制性的(但我們的應用程序使用了一個確實需要默認構造函數的舊序列化程序,因此可能會出現這種情況)。
然後我發現了一個網頁,指出:
如果是專爲繼承一個類是不可序列,它 可能無法寫一個序列化的子類。具體來說,如果超類沒有提供可訪問的 無參數構造函數,那麼它將不可能爲 。
因此,我得到的消息,我想。似乎核心問題是古典的:我宣稱一個類是可序列化的,但超類不是!我將Serializable接口移到層次結構中,一切都很順利。
但該消息是有點誤導... :-)
不需要一個無參數的構造函數。讓我們閱讀源代碼:
// java.io.ObjectStreamClass
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
Class<?> initCl = cl;
while (Serializable.class.isAssignableFrom(initCl)) {
if ((initCl = initCl.getSuperclass()) == null) {
return null;
}
}
...
}
所以,實際上是無參數的構造函數是在類型層次最近沒有Serializable
類所需。
這意味着可以序列化以下類Domain
。
class Domain implements Serializable {
private final int a;
public Domain(int a) {
this.a = a;
}
}
但類Son
不能:
class Father{
private final int a;
public Father(int a) {
this.a = a;
}
}
class Son extends Father implements Serializable {
public Son(int a) {
super(a);
}
}
謝謝,我用的是序列化的典型方法,但一直提供一個空的構造函數,這是我怎麼想它的工作。 – Pool 2009-11-03 01:16:23