class MyClass extends MyClass2 implements Serializable {
//...
}
在MyClass2是不可序列化的屬性。我怎樣才能序列化(和反序列化)這個對象?
更正:MyClass2當然不是一個接口,而是一個類。
class MyClass extends MyClass2 implements Serializable {
//...
}
在MyClass2是不可序列化的屬性。我怎樣才能序列化(和反序列化)這個對象?
更正:MyClass2當然不是一個接口,而是一個類。
正如其他人指出的,Josh Bloch的Effective Java的第11章是Java序列化中不可或缺的資源。
從章有關你的問題有幾點:
我已經寫了一個快速示例來說明這一點。
class MyClass extends MyClass2 implements Serializable{
public MyClass(int quantity) {
setNonSerializableProperty(new NonSerializableClass(quantity));
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
// note, here we don't need out.defaultWriteObject(); because
// MyClass has no other state to serialize
out.writeInt(super.getNonSerializableProperty().getQuantity());
}
private void readObject(java.io.ObjectInputStream in)
throws IOException {
// note, here we don't need in.defaultReadObject();
// because MyClass has no other state to deserialize
super.setNonSerializableProperty(new NonSerializableClass(in.readInt()));
}
}
/* this class must have no-arg constructor accessible to MyClass */
class MyClass2 {
/* this property must be gettable/settable by MyClass. It cannot be final, therefore. */
private NonSerializableClass nonSerializableProperty;
public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) {
this.nonSerializableProperty = nonSerializableProperty;
}
public NonSerializableClass getNonSerializableProperty() {
return nonSerializableProperty;
}
}
class NonSerializableClass{
private final int quantity;
public NonSerializableClass(int quantity){
this.quantity = quantity;
}
public int getQuantity() {
return quantity;
}
}
MyClass2只是一個界面,所以它沒有任何屬性,只有方法。這就是說,如果你有實例變量本身不可序列化,我知道解決它的唯一方法是聲明這些字段是瞬態的。
例如:
private transient Foo foo;
在聲明場瞬時將在序列化和反序列化過程中被忽略。請記住,當使用瞬態字段反序列化對象時,該字段的值始終爲缺省值(通常爲空)。
請注意,您也可以重寫類的readResolve()方法,以基於在其他系統狀態。
您將需要執行writeObject()
和readObject()
並對這些字段進行手動序列化/反序列化。有關詳細信息,請參閱java.io.Serializable
的javadoc頁面。 Josh Bloch的Effective Java在實現健壯和安全的序列化方面也有一些很好的章節。
您可以通過查看瞬態關鍵字開始,該關鍵字將字段標記爲不是對象持久狀態的一部分。
如果您可以修改MyClass2,解決此問題的最簡單方法是聲明屬性瞬態。
這不回答問題 - 問題狀態MyClass2包含不可序列化的屬性,理想情況下不應修改MyClass2。 – 2012-09-07 18:20:24
你說得對,當我回答時,我沒有仔細閱讀過這個問題。我修改了答案。 – ykaganovich 2012-09-07 18:46:30
XStream是一個偉大的庫,用於爲任何對象執行快速的Java到XML序列化,而不管它是否可序列化。即使XML目標格式不適合您,您也可以使用源代碼來學習如何執行此操作。
取決於MyClass2的成員不可序列化的原因。
如果說MyClass2不能用序列化的形式表示,那麼很可能是同樣的原因適用於MyClass,因爲它是一個子類。
通過實現readObject和writeObject,可以爲MyClass編寫自定義序列化表單,從而可以從序列化數據中適當地重新創建MyClass中的MyClass2實例數據的狀態。如果MyClass2的API已修復並且您無法添加Serializable,那麼這將是一條路。
但首先你應該弄清楚爲什麼MyClass2不可序列化,並且可能改變它。
用於串行化不可序列類的實例的有用方法(或在至少子類)是已知的串行代理。從本質上講,你實現了writeReplace來返回一個完全不同的可序列化的類的實例,它實現了readResolve來返回原始對象的副本。我寫了一篇關於Usenet
幾種可能性連載java.awt.BasicStroke中的一個例子POP操作了,我在這裏繼續他們:
如果可能的話,非serialiable部分可以設置爲瞬時
private transient SomeClass myClz;
否則,你可以使用Kryo。 Kryo是用於Java的快速高效的對象圖形序列化框架(例如java.awt.Color的JAVA序列化需要170個字節,Kryo只有4個字節),它還可以序列化非可序列化的對象。 Kryo還可以執行自動深層和淺層複製/克隆。這是直接從對象複製到對象,而不是object->bytes->object
。
kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));
可以修改MyClass2與否:
下面是一個例子,如何使用KRYO
序列化對象可以通過註冊一個確切的串行器也被壓縮?是否需要通過序列化來保留不可序列化的屬性值? 正確的方法取決於此。 – erickson 2008-09-18 18:30:29
MyClass2可以修改。但是,最好不要,因爲我建立在它之上,並且可以被其他人修改。 – Burkhard 2008-09-19 11:04:41