背景
我有一个类,它没有覆盖序列化功能,也没有serialVersionUID
,但仍然被序列化,存储,以后反序列化。这是一个配置对象,当更改配置时,实际上从配置UI读取数据,然后通常“从头开始”创建对象并序列化以进行存储。只有在使用它时,才能通过反序列化来创建对象。
现在有两个字段被添加到这个类中,它不应该被序列化,但是......这当然会导致一些反序列化问题(当默认反序列化后字段保留为null,打破类不变量时出现NullPointerException),解决了通过打开配置UI并保存配置,从而保存对象的正确序列化形式。
问题
现在,如果我以其中一种方式修改类,那么在保存的配置数据中对象的反序列化会发生什么,以便快速修复:
为了使这更具体,让我们说添加的字段是:
private final Map<String, String> extraProperties = new HashMap<String, String>();
这可以从此课程中删除,也可以更改为private final transient
字段。
PS。无需告诉我,可能会添加自定义序列化代码 ,然后 可能可能会被重构,以将持久性和瞬态数据分离到不同的类。
答案 0 :(得分:2)
删除(或暂时)您不想序列化的这些冗余字段。然后尝试反序列化加载旧版本,其中现在已删除的非瞬态字段已存在。这当然会导致错误,因为类serialVersionUID
现在不同了。但是,新邮件serialVersionUID
应该包含在邮件中。
现在只需在您的班级中定义private static long serialVersionUID =
,将其设置为旧的,之前的值。将加载文件中包含多余字段的类内容,并忽略这些多余字段的值。
但是你现在有另一个问题:你可能已经保存了两种不同类型的文件:旧版本。这些将具有不同的serialVersionUID,因此我们可以加载一个或另一个,但不能同时加载两个。 serialVersionUID是最终的,但也许你仍然可以设置和探测不同的值为described here。
从序列化的角度来看,将字段更改为瞬态与字段删除相同。它不会被存储也不会被加载。但是,将先前非瞬态字段声明为瞬态将会更改serialVersionUID
,如果它不是固定的。
如果逐项,如果,serialVersionUID现在已经硬编码且与文件中的serialVersionUID匹配,则问题的答案是:
因为“没有”我的意思是该类被反序列化而没有为瞬态字段赋值(如果存在)并且没有报告错误。
如果serialVersionUID不匹配,则抛出异常,即使其余类匹配。