Java反序列化,将字段更改为瞬态

时间:2013-01-11 08:26:55

标签: java serialization

背景

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

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

问题

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

  1. 删除这些字段,保存的数据是新版本,其中包含这些字段吗?
  2. 将这些字段更改为瞬态,保存的数据是新版本,其中包含这些字段吗?
  3. 将这些字段更改为瞬态,保存的数据是旧版本,没有这些字段?
  4. 为了使这更具体,让我们说添加的字段是:

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

    这可以从此课程中删除,也可以更改为private final transient字段。

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

1 个答案:

答案 0 :(得分:2)

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

现在只需在您的班级中定义private static long serialVersionUID =,将其设置为旧的,之前的值。将加载文件中包含多余字段的类内容,并忽略这些多余字段的值。

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

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

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

  1. 无。
  2. 无。
  3. 没有
  4. 因为“没有”我的意思是该类被反序列化而没有为瞬态字段赋值(如果存在)并且没有报告错误。

    如果serialVersionUID不匹配,则抛出异常,即使其余类匹配。