我有一个序列化为文件的对象列表:
class MyClass implements Serializable {
public String location;
public SomeClass lastUpdatedAt;
}
不幸的是,我现在有了这个类的新版本,我们不再拥有SomeClass了;原因很复杂,但我需要将其序列化为这种新形式(这是一个示例类,而不是实际的类):
class MyClass implements Serializable {
public String location;
}
简而言之,我想在反序列化时忽略一个属性。
请注意,我无法更改原始类源文件。我只有新的源文件
但 ObjectInputStream 在尝试在类路径中找到 SomeClass 时失败:
try {
FileInputStream fis;
ObjectInputStream is;
File f = getSavedFile();
if (f.exists()) {
fis = new FileInputStream(f);
is = new ObjectInputStream(fis);
ArrayList<MyClass> result = (ArrayList<MyClass>) is.readObject(); //fails
is.close();
fis.close();
}
}
catch (Exception e) {
//ClassNotFound exception because SomeClass is not on the classpath.
e.printStackTrace();
}
我知道你可以扩展 ObjectInputStream 并在那里实现一些东西,但我不太熟悉序列化,并希望有人解决了同样的问题。
答案 0 :(得分:1)
使其成为瞬态会将其从序列化中排除
public transient SomeClass lastUpdatedAt;
变量可能会标记为瞬态,表示它们不属于某一部分 对象的持久状态。
答案 1 :(得分:1)
class MyClass implements Serializable {
public String location;
public transient SomeClass lastUpdatedAt;
}
也许你有成功。如果不起作用,则必须覆盖该方法。
出于这个原因,我不喜欢自动序列化,我手动执行:实现序列化的字段和方法。
每次更新代码时,如果使用内置功能,则会出现向后兼容性问题。
答案 2 :(得分:0)
ArrayList<MyClass> result = (ArrayList<MyClass>) is.readObject(); //fails
实际上这会失败,因为元素列表签名不匹配!因为MyClass有1个或多个字段已重命名,添加,删除,所以类型已更改。
MyClass { int a; }
MyClass { String a; }
将打破反序列化。
您可以尝试覆盖equals()
和hashCode()
方法,以使MyClassNew看起来像MyClass。
Here您可以看到更多如何覆盖所需的方法。这应该会给你一个解决方案。
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
location = (String) stream.readObject();
}