我有一个这种形式的课程:
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private Object fields[];
// Methods, etc.
}
有一段时间没关系,但是现在(为了便于阅读和维护)已经转变为:
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private String field1;
private String field2;
private Boolean fiedl3;
// Methods, etc.
}
当您托盘读取具有新类版本的旧文件时,问题就出现了。如果使用不同的serialVersionUID,则不兼容。如果你使用相同的serialVersionUID,我需要实现一些东西来使它兼容。这是我的aproach,覆盖private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
所以我可以手动检查文件中对象的版本。
问题再次出现在我想要使用java.io.ObjectInputStream.defaultReadObject();
所以它会自动为下一个版本做出“魔力”(在新的字段中将是可选的)。所以我有类似的东西:
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private String field1;
private String field2;
private Boolean fiedl3;
// Methods, etc.
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
Object obj = in.readObject();
if (obj instanceof Object[]) {
Object[] tmp = (Object[])obj;
field1 = (String)obj[0];
field2 = (String)obj[1];
// ....
} else {
in.defaultReadObject();
}
}
}
问题在于,由于我已经阅读了部分流,因此defaultReadObject方法崩溃。
我搜索了一个允许你两次读取对象的Stream,但我找不到它。我也知道我可以手动完成读取,但每次我添加另一个字段时我都需要修改它(在defaultReadObject
中,因为它写入字段名称,它只能恢复自动读取的字段)。
所以我的问题是¿我怎么能做到?
注意:我只需要兼容性是从新类读取旧类对象和从新类对象读取新类对象。此外,我已经阅读了其他问题,但他们只回答如何计划一个好的课程以保持兼容性(我之前应该阅读它:-()。
答案 0 :(得分:1)
我找到的唯一解决方案是保持对旧字段的引用。请注意,您可以将其设置为transient
,因为它不会被读取,因此您必须永远携带它。
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private Object fields[]; // So we can read it in old saved version.
private String field1;
private String field2;
private Boolean fiedl3;
// Methods, etc.
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
if (fields != null) {
// If we have read an old version.
field1 = (String)fields[0];
field2 = (String)fields[1];
field3 = (Boolean)fields[2];
// ....
// We set fields to null so no more space is waste than necessary.
fields = null;
}
}
}