Java序列化,UID没有改变。我可以在课程中添加新的变量和方法吗?

时间:2010-11-08 14:18:29

标签: java serialization

我有一个序列化的类。现在我需要使用setter和getter方法在类中添加一个新变量。该类在RMI中通过线路发送。

在不更改UID的情况下,我可以为它添加新参数和getter以及setter方法吗?我尝试编写一个通过线路发送的示例类,并没有更改UID,并为其添加了新参数和getter以及setter方法。另一方面,我测试了它,我仍然得到了正确的值。我曾经假设,如果我添加新参数,getter和setter方法,我需要更改UID。我错了吗?

4 个答案:

答案 0 :(得分:35)

如果您对类的SerialVersionUID进行硬编码(通常为1L),存储一些实例,然后重新定义该类,您基本上会得到这种行为(这或多或少是常识):

  1. 新字段(存在于类定义中,不存在于序列化实例中)被赋予一个默认值,对于对象为null,或者与基元的未初始化字段具有相同的值。
  2. 删除的字段(不在类定义中但存在于序列化实例中)只是被忽略。
  3. 因此,一般的经验法则是,如果您只是添加字段和方法,并且不更改任何现有内容,并且如果您对这些新字段的默认值没有问题,那么您通常可以。

答案 1 :(得分:24)

哇,很多不好的信息。

Java序列化非常强大。有一套非常明确的规则来管理具有相同uid和不同数据的对象的向后兼容性。基本思想是,只要不更改现有成员的类型,就可以保持相同的uid而不会出现数据问题。

说,你的代码仍然需要聪明地处理可能缺少数据的类。该对象可以正确反序列化,但某些字段中可能没有数据(例如,如果您向该类添加了一个字段并且正在反序列化该类的旧版本)。如果你的代码可以处理这个,那么你可以保留当前的uid。如果没有,那么你应该改变它。

除了预定义的规则之外,还有一些高级使用场景,您甚至可以更改现有字段的类型并仍然设法反序列化数据,但这通常只在极端情况下才有必要。

java序列化在网上得到很好的记录,你应该能够在相关的sun / oracle教程/ docs中找到所有这些信息。

答案 2 :(得分:1)

这只有在您让Java为您的类生成默认UID时才有意义。它使用类的实际成员和方法来生成它,从而在更改类结构后使其无效。如果您为您的班级提供UID,那么只有在您需要从文件等反序列化您的类的旧版本时才会这样做。

答案 3 :(得分:0)

想要定义几点来突出显示影响序列化的更改。 您可以在下面找到Oracle Java Docs的链接以获取更多详细信息。

不兼容的更改

对类的不兼容更改是那些无法保证互操作性的更改。在进化课程时可能发生的不兼容的变化是:

  1. 删除字段
  2. 在层次结构中向上或向下移动类
  3. 将非静态字段更改为静态字段或非瞬态字段为瞬态
  4. 更改原始字段的声明类型
  5. 更改writeObject或readObject方法,使其不再写入或读取默认字段数据或更改它,以便在先前版本没有时尝试写入或读取它。
  6. 将类从Serializable更改为Externalizable,反之亦然。
  7. 将类从非枚举类型更改为枚举类型,反之亦然。
  8. 删除Serializable或Externalizable。
  9. 将writeReplace或readResolve方法添加到类中,如果该行为会产生与该类的任何旧版本不兼容的对象。
  10. 从上述信息的链接 http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html#6678