سؤال

I have an array of objects that I am able to read and write to disk. But now I want to add a member variable to my class. If I add the member variable, I'll get a class incompatible error and I won't be able to read my serialized objects. Is there a way to modify the member variables of a class used for serialization without losing the ability to read persisted objects...or an easy way to convert the persisted objects to the new class?

هل كانت مفيدة؟

المحلول

This post from SO that should answer your question. It even explains how to find the serial version automatically created by compiler if you didn't specify it (find serialver in referenced page). Old articles can still be interesting ... In short for the impatient :

  • serialization automagically deals with new or removed members provided serialversion does not change
  • IDEs or the serialver tool of the JDK can give you the serial version automatically generated by the compiler if you did not specify it

So you just have to find this serialversion, add the magic field static final long serialVersionUID = xx and as you are only adding a member variable all should be fine.

(The referenced post is first answer from google for java serialization multiple versions)

نصائح أخرى

If I add the member variable, I'll get a class incompatible error.

No you won't, unless you forgot to define a serialVersionUID value for the class. If you did, use the serialver utility on the original version of the class to tell you what to add.

Adding a field to a serializable class is entirely benign. See the Versioning chapter of the Object Serialization Specification for full details of what you can do to a class before breaking its compatibility under serialization.

First of all, Java serialization isn't intended for object persistence, as the problem you are having highlights.

There is however a workaround (which will get you going in the short term) - add a serialVersionUID to your class and do not change when you modify the class in ways that effect its serialized form.

This is, imho, an abuse of the serialVersionUID but will fix your problem allowing you to add and remove fields at the expense that your system may become brittle if different JVMs use different versions of your class (there's ways to deal with this other than incrementing the serialVersionUID detailed in the link in @EJP's answer) as fields are set to default values meaning while your system may not throw exceptions when the results are not what the user expected and you have a subtle bug that's much harder to find than a serialization error.

All classes get a serialVersionUID - one is generated by the serialization runtime if you haven't declared one. By declaring a serialVersionUID you're telling the serialization runtime, don't generate one because you know the serialized form of the classes is compatible with one built earlier, for example if you added a toString method after the initial compilation that required a rebuild or have taken steps to ensure different versions serialize correctly (again, the link in @EJP's answer).

After adding the class variable make sure both the sending and the receiving sides have the new version of this class they are serializing/deserializing. That should fix your issue.

Of course, also regenerate the disk/serialized data.

Just to chip in, incrementing the serialVersionUID is a good practice. Serialization uses it to ensure the classes on both ends are the same and the saved data is compatible with the current classes.

====

After looking at some of the comments, I want to add why serialVersionUID can be a BAD thing. Bottom line, it must be maintained manually. In a shop with strong procedures in place, that's not a problem. However, simply adding one and then ignoring it or updating it half the time leads to a false sense of security. It appears to be helping, but it's not.

Here are a few thoughts:

  • The compiler issues a warning if a Serialiable class doesn't have a serialVersionUID, so add one. Allowing warnings to accumulate makes them useless.
  • Create a standard and then follow it. Choosing not to update the value is valid, but it means you have to find another way to keeping the class matched between systems.
  • If you don't intend to update the value as the class properties change, then set the value to -1 as an indicator.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top