7

My question is what is a good way to implement upgrading outdated objects?

For example say you have a class like this:

public class Foo() implements Serializable {
    int a;
    String b;
}

and then you serialize this object. Then later on you add more functionality to your class by say adding:

...
int c;
...

You still want to retain the information that is in the serialized object but I know that if you try to deserialize it there will be conflicts. So is there a way (maybe by checking serialVersionUID) to set a value for int c knowing that it won't exist?

Thanks

2
  • did you mean you want to add an int c or something later? Because b is already a String.
    – asgs
    Commented Nov 22, 2012 at 8:47
  • Haha yes I did, silly me. It's late Commented Nov 22, 2012 at 8:58

2 Answers 2

3

Deprecate the existing class, create a new class with the new structure and implement a constructor in the new class that can take the old object and convert it to the new version.

Assuming you created your old class against an interface, you can implement the same interface with the new class and the new objects will still be compatible with your old class.

3
  • I don't think that will work because I still have to read in an incompatible class which will throw an error. Commented Nov 22, 2012 at 9:21
  • Not sure I'm with you . . . you would read the object back in using the original class, there would be nothing incompatible, once the object had been converted, you would then serialise as the new object type.
    – codeghost
    Commented Nov 22, 2012 at 9:26
  • Oh I didn't realize you were meaning to still use the old class. But doing this would also mean that my new class would have to have a different name and my question is for the constant development of a class so that would get annoying. Sorry Commented Nov 22, 2012 at 9:29
1

You would need to add a private method:

    private void readObject(ObjectInputStream ois) {
      // compare serialVersionUID and determine which fields to expect
      // read the expected fields for that version
      // initialize the new fields.
    }

For more information, read the serialization specs

6
  • I looked at what you linked to and that's very helpful. It says that you can implement the readObject function like you said. But Java still complains about the serialVersionUID being different. How exactly do I implement this function? Commented Nov 22, 2012 at 9:24
  • I put this function in my class and put in Foo obj = (Foo) ois.readObject(); ObjectStreamClass.lookup(obj.getClass()).getSerialVersionUID() according to a site i found but it's still not letting it work because of the different serialVersionUID's. What it's looking like I can do is have a different variable to monitor versions and check that to see what to do because then it won't error. Please correct me if I am wrong because I want to do this the correct way and I want to learn. Commented Nov 22, 2012 at 9:49
  • You're probably right - please code and confirm. Just keep track of your version might be simpler - like 1 or 2, or even the version can be the number of fields, so your version difference will tell you how many field values you need to read. Commented Nov 22, 2012 at 9:52
  • Thanks a lot. Very smart idea about using number of fields for version number. So I tried doing this but I just can't seem to figure out what to put in the function. I can't figure out how to check the variable of the serialized object. I tried doing a ois.readObject and then reading that varaible but then I get an OptionalDataException. Also tried doing ois.defaultReadObject and then accessing by this.version but that only showed the current version, not the one I saved with. Commented Nov 22, 2012 at 17:37
  • Hey @akberc. Thank you so much for all of your help. I figured out a way to do it, although I don't know if it's the best way haha. What I did was made a static final int NUM_OF_FIELDS and a int version variable. I'll have to change both of those when I update the class but it works. In the readObject function I just compare this.version and Foo.NUM_OF_FIELDS and that seems to work for what I need. Thanks again! Commented Nov 23, 2012 at 3:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.