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.
You can't serialise a class that doesn't implement Serializable , but you can wrap it in a class that does. To do this, you should implement readObject and writeObject on your wrapper class so you can serialise its objects in a custom way.
the non-serializable field's Class must have an API to allow getting it's state (for writing to the object stream) and then instantiating a new instance with that state (when later reading from the object stream.)
The class will not be serialisable, unless the field is declared transient (which will prevent the field from being serialised, i.e. it will not be saved).
In Java, a NotSerializableException exception is thrown when an instance of a class must implement the Serializable interface. The exception is thrown by either the serialization runtime, or by the instance of the class. The argument for the NotSerializableException is the name of the class.
For serializing the object, we call the writeObject () method of ObjectOutputStream class, and for deserialization we call the readObject () method of ObjectInputStream class. We must have to implement the Serializable interface for serializing the object. Advantages of Java Serialization
Wrap the non-serializable class in a class of your own that implements Serializable. In your class's writeObject method, do whatever's necessary to serialize sufficient information on the non-serializable object so that your class's readObject method can reconstruct it.
Deserialization is the process of reconstructing the object from the serialized state. It is the reverse operation of serialization. Let's see an example where we are reading the data from a deserialized object. If a class implements Serializable interface then all its sub classes will also be serializable.
Specifically, as will be demonstrated in this post, custom serialization can be used to allow a larger object to be serialized even when attributes of that object are not themselves directly serializable.
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;
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With