我遇到了 Java 序列化的问题。假设我有一个对象持久化到文件系统。我们如何根据后一个版本中的对象结构修改来更新文件的结构?
例如,如果我保存了 Object
A{int a; String b} to file
我改变了一个结构,A{int a; String b, char c}
有什么办法可以根据 A 的后一版本更改以前保存的文件?
我遇到了 Java 序列化的问题。假设我有一个对象持久化到文件系统。我们如何根据后一个版本中的对象结构修改来更新文件的结构?
例如,如果我保存了 Object
A{int a; String b} to file
我改变了一个结构,A{int a; String b, char c}
有什么办法可以根据 A 的后一版本更改以前保存的文件?
这是可能的。您需要使下一个版本与以前的版本向后兼容。Java 序列化规范中解释了执行此操作的方法:http: //docs.oracle.com/javase/1.3/docs/guide/serialization/spec/version.doc.html。
然而,这个问题是一个很好的例子,说明为什么使用本机 Java 序列化来长时间持久化对象通常是一个坏主意。如果您使用了特定格式(XML、JSON 或其他格式),您可以轻松读取和转换文件本身,或者能够读取具有不同序列化程序实现的文件的任何版本,从而更轻松地从一个版本迁移给另一个。
是的(只要结构不太不同并遵守某些规则)。假设您的文件包含以下内容的序列化表示:
class Foo
{
int a; // value = 42
String b; // value = "don't panic"
}
但是,您现在已经更改了Foo
对象,并且类定义现在是:
class Foo
{
int a;
String b;
char c;
}
当读入你的文件时,序列化机制会自动弹出一个实例Foo
,并将 a 设置为 42,将 b 设置为“不要恐慌”。for 的值c
不在流中,因此默认情况下,它被设置为 Java 默认值(在本例中,对于 char,0x0000)。
现在你有了你的对象,你可以设置值c
:
foo.c = 'Z';
如果您现在序列化您的对象并将其写入文件,则该文件将具有以下序列化表示:
class Foo
{
int a; // value = 42
String b; // value = "don't panic"
char c; // value = 'Z'
}
正如我们在上面看到的,c
当在对象流中找不到它时,它被赋予了一个默认值。您可能想要定义不同的默认值。序列化机制为您在序列化/反序列化时执行自定义代码提供了一种方式。有关详细信息,请查看用于 Serializable的Javadoc (参见 的描述readObject()
)。
编辑:正如 JB Nizet 指出的那样,有一个特殊的序列化字段称为serialVersionUID
. 您需要确保对象中的版本 ID 与对象流中的内容相匹配。您可以像这样在对象中显式设置它:
private static final long serialVersionUID = 1L;
但是,如果您最初没有指定它,它会使用从字段和方法签名的哈希算法生成的值自动写出。如果你需要重新生成这个数字(这样你就可以在你的类中将它定义为一个常量,你需要使用serialver工具。