Java serialization with non-serializable parts

I have:

class MyClass extends MyClass2 implements Serializable { //... } 

In MyClass2, this is a property that is not serializable. How can I serialize (and de-serialize) this object?

Correction: MyClass2, of course, is not an interface, but a class.

+51
java serialization
Sep 18 '08 at 18:15
source share
10 answers

As another noted, chapter 11 of Josh Bloch Efficient Java is an indispensable resource for Java Serialization.

A few points from this chapter related to your question:

  • Assuming you want to serialize the state of a non-serializable field in MyClass2, this field should be available to MyClass, either directly or through getters and setters. MyClass will need to implement custom serialization by providing the readObject and writeObject methods.
  • a non-serializable field The class must have an API that allows it to receive its state (for writing to the stream of objects), and then create an instance of a new instance with this state (during subsequent reading from the stream of objects).
  • for element 74 of effective Java, MyClass2 must have a no-arg constructor available for MyClass, otherwise MyClass will not be able to extend MyClass2 and implement Serializable.

I wrote an example below to illustrate 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; } } 
+50
Sep 18 '08 at 22:24
source share

MyClass2 is just an interface, so it has no properties, but only methods. If you have instance variables that are themselves not serializable, the only way I know to get around this is to declare these fields transient.

Example:

 private transient Foo foo; 

When you declare a field transition period, it will be ignored during the serialization and deserialization process. Keep in mind that when deserializing an object with a transition field, the field value will always be the default (usually null.)

Note that you can also override the readResolve () method of your class to initialize the transition fields based on a different state of the system.

+34
Sep 18 '08 at 18:17
source share

If possible, non-serializable parts can be installed as transitional

 private transient SomeClass myClz; 

Otherwise, you can use Kryo . Kryo is a fast and efficient object graph serialization structure for Java (for example, java.awt.Color JAVA serialization requires 170 bytes, Kryo only 4 bytes), which can also serialize non-serializable objects. Kryo can also perform automatic deep and shallow copying / cloning. This is a direct copy from object to object, not object->bytes->object .

Here is an example of using 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 also be compressed by registering the exact serializer:

 kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class))); 
+16
Nov 12 '12 at 16:51
source share

If you can modify MyClass2, the easiest way to access this is to declare a transitional resource.

+12
Sep 18 '08 at 18:22
source share

You will need to implement writeObject() and readObject() and perform manual serialization / deserialization of these fields. See the javadoc page for java.io.Serializable for more details. Josh Bloch Effective Java also has some good chapters on implementing robust and secure serialization.

+7
18 sept '08 at 18:18
source share

Depends on why this member of MyClass2 is not serializable.

If there is some good reason why MyClass2 cannot be represented in serialized form, then the likelihood of the same can be applied to MyClass, since it is a subclass.

It may be possible to write a custom serialized form for MyClass by implementing readObject and writeObject so that the data state of the MyClass2 instance in MyClass can be recreated accordingly from the serialized data. This would be the way if the MyClass2 API were installed and you cannot add Serializable.

But first you have to find out why MyClass2 is not serializable and maybe change it.

+6
Sep 18 '08 at 18:27
source share

You can start by looking for the transient keyword, which notes that fields are not part of the object's persistent state.

+5
Sep 18 '08 at 18:20
source share

Several possibilities appeared, and I resumed them here:

  • Implement writeObject () and readObject () as sk suggested
  • declare a transient property and it will not be serialized as above hank
  • use XStream as boris-terzic indicated
  • use Serial Proxy as indicated by tom-hawtin-tackline
+5
Sep 22 '08 at 16:33
source share

XStream is a great library for quickly serializing Java for XML for any object, whether it is Serializable or not. Even if the target XML format does not suit you, you can use the source code to find out how to do this.

+4
Sep 18 '08 at 18:23
source share

A useful approach for serializing instances of non-serializable classes (or at least subclasses) is known for Serial Proxy. Essentially, you execute writeReplace to return an instance of a completely different serializable class that implements readResolve to return a copy of the original object. I wrote an example serialization of java.awt.BasicStroke on Usenet

+3
Sep 19 '08 at 10:21
source share



All Articles