The Java object hash code is changed after deserialization

Java serialization: readObject () vs. readResolve ()


The book Effective Java and other sources provide a pretty good explanation of how and when to use the readObject () method when working with serializable Java classes. The readResolve () method, on the other hand, remains a mystery. Basically, all of the documents I've found mention either just one of the two or just both individually.

Questions that go unanswered are:

  • What is the difference between the two methods?
  • When should which method be implemented?
  • How should readResolve () be used, especially with regards to returning what?

I hope you can shed some light on this matter.


Reply:


becomes to Replace of the object read from the stream. The only use I've ever seen for this is forcing singletons. When an object is read, replace it with the singleton instance. This ensures that no one can create another instance by serializing and deserializing the singleton.







Item 90, Effective Java, 3rd Ed Cover, and for serial proxies - their main uses. The examples don't write out and methods because they use standard serialization to read and write fields.

is called after it has returned (conversely, it is called before and probably for another object). The object that the method returns replaces the object returned to the user and any further references to the object in the stream. Both and can return objects of the same or different types. Returning the same type is useful in some cases where fields must be present and either backward compatibility is required or values ​​must be copied and / or validated.

Using does not enforce the Singleton property.


readResolve can be used to modify the data that is serialized through the readObject method. For example, the xstream API uses this function to initialize some attributes that were not in the XML to be deserialized.

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




readResolve is for in case you might need to return an existing object, e.g. For example, because you are looking for duplicate entries that should be merged, or (e.g. in possibly consistent distributed systems) because it is an update that may arrive before you notice older versions.



readObject () is an in ObjectInputStream existing method class. reading the object at the time of deserialization the readObject method internally checks whether the class object to be deserialized has the readResolve method or not, if the readResolve method is present it calls the readResolve method and returns the same example.

The intent of writing the readResolve method is therefore a good practice to achieve a pure singleton design pattern where no one can serialize / deserialize another instance.



When using serialization to convert an object so that it can be saved to a file, we can trigger the readResolve () method. The method is private and is stored in the same class whose object is obtained during deserialization. It ensures that after deserialization, the returned object is the same one that was serialized. This is,

The readResolve () method is not a static method. After being called during deserialization, it just ensures that the object returned is the same as the object that was serialized as follows

In this way, it also helps with the implementation of Singleton design patterns because the same instance is returned every time.


I know this question is very old and has an accepted answer, but since it comes up a lot on google search I thought I would weigh as no answer covers the three cases I think are important - my opinion according to the primary use for these methods. Of course, all of them assume that a custom serialization format is indeed required.

Take collection classes, for example. Standard serialization of a linked list or BST would result in a huge loss of space with very little performance gain compared to simply serializing the items in the order given. This is even more true when a collection is a projection or a view. Reference is made to a larger structure than is made available through the public API.

  1. If the serialized object contains immutable fields that require custom serialization, the original solution of will not be sufficient because the deserialized object before the Reading the inscribed portion of the stream is created. Take this minimal implementation of a linked list:

This structure can be serialized by recursively writing the field of each link followed by a value. However, deserializing such a format becomes impossible: the values ​​of the member fields cannot be changed (now set to). Here comes the / couple:

I'm sorry if the above example doesn't compile (or work), but hopefully it's enough to illustrate my point. If you think this is a very far-fetched example, please keep in mind that there are many functional languages ​​running on the JVM and this approach is essential in your case.

  1. We may actually want to deserialize an object of a different class than what we wrote to. This would be the case with views like a list implementation that exposes a slice of a longer one. Obviously, serializing the entire background list is a bad idea and we should only write the items from the slice shown. But why stop doing it and have a useless amount of indirection after deserialization? We could just read the elements from the stream into one and return it directly instead of including it in our view class.

  2. Alternatively, a similar delegate class dedicated to serialization could be a design choice. A good example would be reusing our serialization code. For example, if we have a Builder class (similar to the StringBuilder for String) we can write a serialization delegate that serializes each collection by writing an empty builder to the stream, followed by the collection size and the items returned by the column's iterator. During deserialization, the builder is read, all subsequently read elements are appended and the result of the final is returned by the delegates. In that case, we would only have to implement serialization in the root class of the collection hierarchy, and no additional code would be required for current or future implementations as long as they abstractly implement and method (the latter for rebuilding the collection of the same type - which in itself is a very useful function would). Another example would be a class hierarchy, the code of which we do not fully control. Our base class (es) from a third-party library can contain any number of private fields that we don't know about and that can change from one version to another of our serialized objects. In this case, it would be safer to write the data and manually re-create the object when deserializing.


The readResolve method

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 to be deserialized. The method is defined as follows:

ANY-ACCESS-MODIFIER The readResolve () object throws an ObjectStreamException.

The readResolve- Method is called when ObjectInputStream has read an object from the stream and is preparing to return it to the caller. ObjectInputStream checks whether the class of the object defines the readResolve method. When the method is defined, the readResolve method is called to allow the object in the stream to set the object to return. The returned object should be of a type that is compatible with all uses. If it's not compatible, a ClassCastException triggered when the Type incongruence found becomes.

For example, a symbol Class can be created for which only a single instance of each symbol binding exists within a virtual machine. The readResolve- Method would be implemented to determine if this symbol has already been defined and the pre-existing equivalent Symbol object replace to keep identity constraint. In this way, the uniqueness of symbol objects can be maintained across serialization.


As answered earlier, it is a private method that is used in ObjectInputStream when deserializing an object. This is called just before the actual instance is returned. In the case of Singleton, we can force the return of an already existing Singleton instance reference instead of a deserialized instance reference. Similarly, for ObjectOutputStream.

Example for :

}}

Output:

We use cookies and other tracking technologies to improve your browsing experience on our website, to show you personalized content and targeted ads, to analyze our website traffic, and to understand where our visitors are coming from.

By continuing, you consent to our use of cookies and other tracking technologies and affirm you're at least 16 years old or have consent from a parent or guardian.

You can read details in our Cookie policy and Privacy policy.