How can I change the names of instance variables in a class which is Serializable and still be able to read serialized files from a previous version of the class? If I use serialver to create a version ID then implement readObject(), how would I know in which order to read in the instance variables from the old serialized files?

Hugh Robinson

One way to solve this is to override the readObject() instance method in the class which you are serializing and whose variable names have changed.

In this method, you can use the ObjectInputStream.readFields() method to return an ObjectInputStream.GetField object, which can then be interrogated one variable at a time.

Suppose that in version 1, the class had instance variables named m_str1 and m_n1 and in version 2, it had m_str2 and m_n2. Then:

private void readObject(java.io.ObjectInputStream in)
             throws IOException, ClassNotFoundException {

   ObjectInputStream.GetField gf = in.readFields();

   if ((String) gf.get("m_str2", null) != null) {
       // Version 2 file detected
       // defaultReadObject() would suffice here, but it's
       // too late to call it!
       m_str2 = (String) gf.get("m_str2", null);
       m_n2 = (int) gf.get("m_n2", null);
   else {
       // Version 1 file detected
       m_str2 = (String) gf.get("m_str1", null);
       m_n2 = (int) gf.get("m_n1", null);
The downside of this is that it seems to take about 150% of the CPU time (I tested it in JDK 1.3, which is faster at serialization than JDK 1.2.2) compared to using the default read mechanism. This may be important if you are reading a lot of objects of this class.

The problem here is that if you call readFields() to determine the version of the class, you have then read all of the persistent fields for the class and you then (presumably) have to get the fields using gf.get(). It would instead be nice to be able to detect the old version without incurring the speed hit when reading the new version.

The only way that I can think of is to write a version number at the beginning of the stream using some Version class. Then the hit would only be felt on one (small) class.