1

My immutable class (all fields final) contains a reference to an object of a 3rd-party class that does not implement Serializable. The usual workaround for this is (as described in the accept answer of How to serialize a non-serializable in Java?) to use the writeObject and readObject methods to create a custom serialization format. However, readObject is unable to update final fields because it isn't a constructor. I've seen a suggestion of using readResolve to work around this, but cannot see how this can work, because I don't see how to get the data necessary to initialise the final field into that method (it apparently only has access to the fields I have already initialised, and I'd really rather not create a new mutable field in the object for temporary use during deserialization when the object is supposed to be entirely immutable). So how can I get my deserialization to work?

public class ThisDoesntWork implements Serializable
{
   private final transient SomeNonSerializableClass object;
   private void writeObject (ObjectOutputStream out) throws IOException
   {
      out.writeUTF (object.toString());
   }
   private void readObject (ObjectInputStream in) throws IOException
   {
      object = SomeNonSerializableClass.fromString(in.readUTF()); // error!
   }
}
Community
  • 1
  • 1
Jules
  • 14,841
  • 9
  • 83
  • 130
  • You could just remove the `final` keyword. Your class is still immutable even if you remove it, because you control all access to the field. That's why you encapsulate fields. You could leave `final` as a comment, for documentation purposes, e.g. `private /*final*/ MyObject myObj`. – Andreas Jul 22 '16 at 22:47

1 Answers1

2

You use writeReplace() to write an object of a different (proxy) class, and readResolve() to construct an object of the original class from the values in the proxy. The constructor can set the final field.

user207421
  • 305,947
  • 44
  • 307
  • 483