Reputation: 14738
I have:
class MyClass extends MyClass2 implements Serializable {
//...
}
In MyClass2 is a property that is not serializable. How can I serialize (and de-serialize) this object?
Correction: MyClass2 is, of course, not an interface but a class.
Upvotes: 56
Views: 103999
Reputation: 6396
You will need to implement writeObject()
and readObject()
and do manual serialization/deserialization of those fields. See the javadoc page for java.io.Serializable
for details. Josh Bloch's Effective Java also has some good chapters on implementing robust and secure serialization.
Upvotes: 6
Reputation: 1516
If possible, the non-serialiable parts can be set as transient
private transient SomeClass myClz;
Otherwise you can use Kryo. Kryo is a fast and efficient object graph serialization framework for Java (e.g. JAVA serialization of java.awt.Color requires 170 bytes, Kryo only 4 bytes), which can serialize also non serializable objects. Kryo can also perform automatic deep and shallow copying/cloning. This is direct copying from object to object, not object->bytes->object
.
Here is an example how to use kryo
Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
Serialized objects can be also compressed by registering exact serializer:
kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));
Upvotes: 15
Reputation: 10948
XStream is a great library for doing fast Java to XML serialization for any object no matter if it is Serializable or not. Even if the XML target format doesn't suit you, you can use the source code to learn how to do it.
Upvotes: 4
Reputation: 14964
If you can modify MyClass2, the easiest way to address this is declare the property transient.
Upvotes: 11
Reputation: 14738
Several possibilities poped out and i resume them here:
Upvotes: 5
Reputation: 147164
A useful approach for serialising instances of non-serializable classes (or at least subclasses of) is known a Serial Proxy. Essentially you implement writeReplace to return an instance of a completely different serializable class which implements readResolve to return a copy of the original object. I wrote an example of serialising java.awt.BasicStroke on Usenet
Upvotes: 3
Reputation: 279255
Depends why that member of MyClass2 isn't serializable.
If there's some good reason why MyClass2 can't be represented in a serialized form, then chances are good the same reason applies to MyClass, since it's a subclass.
It may be possible to write a custom serialized form for MyClass by implementing readObject and writeObject, in such a way that the state of the MyClass2 instance data in MyClass can be suitably recreated from the serialized data. This would be the way to go if MyClass2's API is fixed and you can't add Serializable.
But first you should figure out why MyClass2 isn't serializable, and maybe change it.
Upvotes: 6
Reputation: 10829
As someone else noted, chapter 11 of Josh Bloch's Effective Java is an indispensible resource on Java Serialization.
A couple points from that chapter pertinent to your question:
I've written a quick example below illustrating this.
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;
}
}
Upvotes: 51
Reputation: 18397
MyClass2 is just an interface so techinicaly it has no properties, only methods. That being said if you have instance variables that are themselves not serializeable the only way I know of to get around it is to declare those fields transient.
ex:
private transient Foo foo;
When you declare a field transient it will be ignored during the serialization and deserialization process. Keep in mind that when you deserialize an object with a transient field that field's value will always be it's default (usually null.)
Note you can also override the readResolve() method of your class in order to initialize transient fields based on other system state.
Upvotes: 35
Reputation: 2907
You can start by looking into the transient keyword, which marks fields as not part of the persistent state of an object.
Upvotes: 5