问题
I am going through Effective Java, item 75:
If all instance fields are transient, it is technically permissible to dispense with invoking defaultWriteObject and defaultReadObject , but it is not recommended. Even if all instance fields are transient, invoking defaultWriteObject affects the serialized form, resulting in greatly enhanced flexibility. The resulting serialized form makes it possible to add nontransient instance fields in a later release while preserving backward and forward compatibility. If an instance is serialized in a later version and deserialized in an earlier version, the added fields will be ignored. Had the earlier version’s readObject method failed to invoke defaultReadObject , the deserialization would fail with a StreamCorruptedException
The question is why it's necessary to call defaultReadObject/defaultWriteObject to preserve backward and forward compatibility?
Can you explain with an example?
Why the added fields will be ignored?
Why a StreamCorruptedException will be thrown?
回答1:
Because that's what happens by default. If you add these methods you have to at least do what would have happened if they weren't present. Otherwise you won't read/write the stream in a compatible manner. You can't just completely replace what would have been written without risking compatibility.
Unless you can magically change both ends at the same time and there are no permanently serialized streams anywhere, e.g. in files or a database.
回答2:
The answer to your question is actually in the excerpt you just provided (though it is a bit vague, I admit). The crucial part is this:
If an instance is serialized in a later version and deserialized in an earlier version, the added fields will be ignored. Had the earlier version’s readObject method failed to invoke defaultReadObject, the deserialization would fail [...]
Imagine the following example:
You have an object with only transient fields in it. You decide to skip defaultWriteObject/defaultReadObject
calls, because you assume that you do not need it.
Then you add new features to your program, and you also add some non-transient fields to this object. You call defaultWriteObject
properly this time, and you expect that the old version of your application will still function (ignoring the new field of course). But it won't. Instead of ignoring the new field you just added because it found unexpected data there.
来源:https://stackoverflow.com/questions/33363646/why-readobject-method-must-call-defaultreadobject-to-preserve-backward-and-forwa