Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java serialization: readObject() vs. readResolve()

People also ask

What is the purpose of readResolve () method in serialization?

For Serializable and Externalizable classes, the readResolve method allows a class to replace/resolve the object read from the stream before it is returned to the caller. By implementing the readResolve method, a class can directly control the types and instances of its own instances being deserialized.

What is readObject in Java?

The method readObject is used to read an object from the stream. Java's safe casting should be used to get the desired type. In Java, strings and arrays are objects and are treated as objects during serialization. When read they need to be cast to the expected type.

What is the difference between serialization and de serialization?

Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory.

Which method is used for object deserialization?

For serializing the object, we call the writeObject() method of ObjectOutputStream class, and for deserialization we call the readObject() method of ObjectInputStream class.


readResolve is used for replacing the object read from the stream. The only use I've ever seen for this is enforcing singletons; when an object is read, replace it with the singleton instance. This ensures that nobody can create another instance by serializing and deserializing the singleton.


Item 90, Effective Java, 3rd Ed covers readResolve and writeReplace for serial proxies - their main use. The examples do not write out readObject and writeObject methods because they are using default serialisation to read and write fields.

readResolve is called after readObject has returned (conversely writeReplace is called before writeObject and probably on a different object). The object the method returns replaces this object returned to the user of ObjectInputStream.readObject and any further back references to the object in the stream. Both readResolve and writeReplace may return objects of the same or different types. Returning the same type is useful in some cases where fields must be final and either backward compatibility is required or values must copied and/or validated.

Use of readResolve does not enforce the singleton property.


readResolve can be used to change the data that is serialized through readObject method. For e.g. xstream API uses this feature to initialize some attributes that were not in the XML to be deserialized.

http://x-stream.github.io/faq.html#Serialization


readObject() is an existing method in ObjectInputStream class. While reading object at the time of deserialization readObject() method internally check whether the class object which is being deserialized having readResolve() method or not. If readResolve() method exists then it will invoke it and return the same instance.

So the intent of writing readResolve() method is a good practice to achieve pure singleton design pattern where no one can get another instance by serializing/deserializing.


readResolve is for when you may need to return an existing object, e.g. because you're checking for duplicate inputs that should be merged, or (e.g. in eventually-consistent distributed systems) because it's an update that may arrive before you're aware of any older versions.


readResolve() will ensure the singleton contract while serialization.
Please refer


When serialization is used to convert an object so that it can be saved in file, we can trigger a method, readResolve(). The method is private and is kept in the same class whose object is being retrieved while deserialization. It ensures that after the deserialization, what object is returned is the same as was serialised. That is, instanceSer.hashCode() == instanceDeSer.hashCode()

readResolve() method is not a static method. After in.readObject() is called while deserialisation it just makes sure that the returned object is the same as the one which was serialized as below while out.writeObject(instanceSer)

..
    ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file1.ser"));
    out.writeObject(instanceSer);
    out.close();

In this way, it also helps in singleton design pattern implementation, because every time same instance is returned.

public static ABCSingleton getInstance(){
    return ABCSingleton.instance; //instance is static 
}