2

Suppose a class implements serializable and I serialize an object of the class. After ding so I change internal implementation such that I change data type of one the variable from int to String.. Is it possible to obtain the values from the serialized object while deserialization using readresolve?

Class A implements Serializable{
  private int first;
  private int second;

}

after the serialization:

Class A implements Serializable{

 private int first;
 private String second;

}
Yatin Garg
  • 141
  • 1
  • 8
  • Why don't you try it? Save the class to a file, change it, try to read it (Hint: changing the type of *existing* members is an incompatible change). – dhke Jun 23 '15 at 13:34

2 Answers2

2

You'd need to implement a custom readObject() method. More info here.

The serialVersionUID would also need to be the same in both versions of the class. If you don't already declare a serialVersionUID then the jvm will calculate it based on the shape of the class. For this to work you would need to explicitly declare the old serialVersionUID in the new version of the class. More info here

Community
  • 1
  • 1
lance-java
  • 25,497
  • 4
  • 59
  • 101
  • There is also [Java's own explanation](http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html). – VGR Jun 23 '15 at 13:36
  • serialversionId alone is required if I am adding a new field... for changing a data member's data type.. what should I do? – Yatin Garg Jun 23 '15 at 18:35
  • You will also need to define `serialPersistentFields` to specify the old types. You can add extra serialised fields to this with different names. (Also you will need a `writeObject` method.) – Tom Hawtin - tackline Jun 24 '15 at 03:34
1

Bored. Let's try this (not compiled)...

import java.io.*;

class A implements Serializable {
    private static final long serialVersionUID = 0x...L;
    private static final ObjectStreamField[] serialPersistentFields = {
        new ObjectStreamField("first", int.class),
        new ObjectStreamField("second", int.class),
        new ObjectStreamField("secondString", String.class),
    };
    private int first;
    private String second;

    private void writeObject(ObjectOutputStream out) throws IOException {
         ObjectOutputStream.PutField fields = out.putFields();
         fields.put("first", first);
         int secondInt;
         try {
             secondInt = Integer.parseInt(second);
         } catch (NumberFormatException exc) {
             secondInt = -1;
         }
         fields.put("second", secondInt);
         fields.put("secondString", second);
     }
     private void readObject(
         ObjectInputStream in
     ) throws IOException, ClassNotFoundException {
         ObjectInputStream.GetField fields = out.readFields();
         fields = fields.get("first", 0);
         int secondInt = fields.get("second", 0);
         second = (String)field.get("secondString", Integer.toString(secondInt));
     }
}

If either of the fields were final, then you'd need readResolve weirdness or worse.

(Almost left the last secondInt as second there. Boo hiss to String.valueOf.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305