3

背景

我有一个类,它没有覆盖序列化功能,也没有serialVersionUID,但它仍然被序列化、存储、稍后反序列化。这是一个配置对象,在更改配置时,实际上是从配置 UI 中读取数据,然后“从头开始”正常创建对象并序列化存储。只有在使用它时,才会通过反序列化创建对象。

现在这个类中添加了两个字段,它们不应该被序列化,但是......这当然会导致一些反序列化问题(默认反序列化后字段为空时出现 NullPointerException,破坏类不变量),通过打开配置解决UI 和保存配置,从而保存对象的正确序列化形式。

问题

现在,如果我以其中一种方式修改类以进行快速修复,那么从保存的配置数据中反序列化对象会发生什么:

  1. 去掉这些字段,保存的数据是新版本,有这些字段吗?
  2. 将这些字段更改为瞬态,并且保存的数据是新版本,其中包含这些字段吗?
  3. 将这些字段更改为瞬态,保存的数据是旧版本,没有这些字段?

为了更具体,假设添加的字段是:

private final Map<String, String> extraProperties = new HashMap<String, String>(); 

这要么从此类中删除,要么更改为private final transient字段。

PS。无需告诉我,可能应该添加自定义序列化代码然后可能应该重构整个事情以将持久性和瞬态数据分离到不同的类......

4

1 回答 1

2

删除(或使临时)这些您不想序列化的冗余字段。然后尝试反序列化加载已存在非瞬态字段的旧版本。这当然会导致错误,因为类serialVersionUID现在不同了。但是,新旧serialVersionUID都应包含在消息中。

现在只需private static long serialVersionUID =在您的类中定义,将其设置为旧的先前值。文件中带有多余字段的类内容将被加载,这些多余字段的值将被忽略。

但是,您现在遇到了另一个问题:您可能保存了两种不同类型的文件:旧版本和新版本。这些将具有不同的serialVersionUID,因此我们可以加载一个或另一个,但不能同时加载。serialVersionUID 是最终的,但也许您仍然可以设置和探测不同的值,如此处所述

从序列化的角度来看,将字段更改为瞬态与字段删除相同。它不会被存储,也不会被加载。serialVersionUID但是,如果它不固定,则将先前的非瞬态字段声明为瞬态将改变它。

如果逐项,如果serialVersionUID 现在是硬编码与文件中的 serialVersionUID 匹配,那么您的问题的答案是:

  1. 没有。
  2. 没有。
  3. 没有。

As "nothing" I mean that the class is deserialized without assigning values to the transient fields (if these are present) and no error is reported.

In case serialVersionUID's do not match, an exception is thrown, even if the rest of class matches.

于 2013-01-11T10:31:36.543 回答