我继承了以下代码(以及使用它存储的数据,即 A 的序列化实例):
class A implements Serializable {
private static final long serialVersionUID = 1L;
int someField;
B b;
}
class B implements Serializable {
private static final long serialVersionUID = 1L;
int someField;
}
在某些时候,我意识到 A
中的 b
字段实际上不应该被持久化(并且 B
根本不应该被序列化),所以我将其更改为:
class A implements Serializable {
private static final long serialVersionUID = 1L;
int someField;
transient B b;
}
class B {
int someField;
}
如果我创建一个 A
的新实例并序列化它,那么反序列化它就没有问题。但是,如果我尝试反序列化与旧代码一起存储的 A
实例,则会收到以下形式的异常:
java.io.InvalidClassException: B; B; class invalid for deserialization
at java.io.ObjectStreamClass.checkDeserialize(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
我相信这是因为持久化数据还存储了 A
和 B
的类描述,而这些人仍然认为 b
> 仍然存在,即使在当前版本中它们不再存在(请参阅 ObjectStreamClass 中的第 600 到 606 行)
有没有办法强制 A 的反序列化跳过现在是 transient 的字段?例如,是否有一种方法可以覆盖反序列化代码在 ObjectInputStream
中读取的类描述并更新其 b
的定义,以便它知道其 transient ?
最佳答案
在反序列化期间没有跳过某些字段的技巧。事实上,(几乎)对类的源代码所做的任何更改都会使旧的序列化数据无法反序列化。序列化将源代码与序列化数据紧密结合。
这就是序列化不适合长期数据存储的原因。序列化仅适用于 RMI(通过网络传输对象)或磁盘上的临时存储等情况。使用记录良好的(标准)文件格式而不是 Java 序列化来进行长期数据存储。
您可以做的是使用旧代码反序列化数据,然后将其写入另一种格式,然后仅使用该格式。
关于java - 反序列化时跳过新的 transient 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2849798/