Java 序列化,UID 未更改。我可以向类中添加新的变量和方法吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4124664/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java serialization, UID not changed. Can I add new variables and method to the class?
提问by javanerd
I have a class that is serialised. Now I need to add a new variable into the class, with setter and getter methods. This class is sent over wire in RMI.
我有一个序列化的类。现在我需要使用 setter 和 getter 方法向类中添加一个新变量。此类在 RMI 中通过线路发送。
Without changing the UID, can I add new parameters and getter and setter methods for it? I tried to write an example class that is sent over wire, and did not change the UID, and added new parameters and getter and setter methods for it. On the other end, I tested it and I still got the values properly. I had assumed, if I add new parameters, getter and setter methods, I need to change the UID. Am I wrong?
在不更改 UID 的情况下,我可以为其添加新参数以及 getter 和 setter 方法吗?我尝试编写一个通过网络发送的示例类,并且没有更改 UID,并为其添加了新参数以及 getter 和 setter 方法。另一方面,我对其进行了测试,但仍然正确地获得了值。我曾假设,如果我添加新参数、getter 和 setter 方法,我需要更改 UID。我错了吗?
回答by romacafe
If you hard-code the SerialVersionUID of a class, (to 1L, usually), store some instances, and then re-define the class, you basically get this behavior (which is more or less common sense):
如果您对类的 SerialVersionUID 进行硬编码(通常为 1L),存储一些实例,然后重新定义该类,您基本上会得到这种行为(或多或少是常识):
- New fields (present in class definition, not present in the serialized instance) are assigned a default value, which is null for objects, or the same value as an uninitialized field for primitives.
- Removed fields (not present in class definition but present in the serialized instance) are simply ignored.
- 新字段(存在于类定义中,不存在于序列化实例中)被分配一个默认值,该值对于对象为 null,或者与原始字段的未初始化字段相同的值。
- 删除的字段(不存在于类定义中,但存在于序列化实例中)被简单地忽略。
So the general rule of thumb is, if you simply add fields and methods, and don't change any of the existing stuff, AND if you're OK with default values for these new fields, you're generally OK.
所以一般的经验法则是,如果您只是添加字段和方法,并且不更改任何现有内容,并且如果您对这些新字段的默认值没问题,那么您通常没问题。
回答by james
Wow, a lot of bad information.
哇,很多不好的信息。
Java serialization is +very+ robust. There are a very well defined set of rules governing backwards compatibility of objects with the same uid and different data. the basic idea is that as long as you don't change the the type of an existing member, you can maintain the same uid without data issues.
Java 序列化非常+ 健壮。有一组非常明确的规则来管理具有相同 uid 和不同数据的对象的向后兼容性。基本思想是,只要不更改现有成员的类型,就可以保持相同的 uid,而不会出现数据问题。
that said, your code still needs to be smart about handling classes with potentially missing data. the object may deserialize correctly, but there may not be data in certain fields (e.g. if you added a field to the class and are deserializing an old version of the class). if your code can handle this, than you can probably keep the current uid. if not, then you should probably change it.
也就是说,您的代码仍然需要聪明地处理可能丢失数据的类。对象可能会正确反序列化,但某些字段中可能没有数据(例如,如果您向类添加了一个字段并且正在反序列化该类的旧版本)。如果您的代码可以处理这个问题,那么您可能可以保留当前的 uid。如果没有,那么您可能应该更改它。
in addition to the pre-defined rules, there are advanced usage scenarios where you could even change the type of existing fields and still manage to deserialize the data, but that generally only necessary in extreme situations.
除了预定义的规则外,还有一些高级使用场景,您甚至可以更改现有字段的类型并仍然设法反序列化数据,但这通常只在极端情况下才有必要。
java serialization is very well documented online, you should be able to find all this information in the relevant sun/oracle tutorials/docs.
java 序列化在网上有很好的文档记录,您应该能够在相关的 sun/oracle 教程/文档中找到所有这些信息。
回答by deorst
This only matters if you let Java generate a default UID for your class. It uses the actual members and methods of the class to generate it, thus making it invalid once you change the class structure. If you provide an UID for your class then this only matters if you need to deserialize older versions of your class from a file and such.
这仅在您让 Java 为您的类生成默认 UID 时才重要。它使用类的实际成员和方法来生成它,因此一旦更改了类结构,它就会失效。如果您为您的班级提供了 UID,那么这仅在您需要从文件等反序列化您班级的旧版本时才重要。
回答by Varun
Want to define few point to highlight the changes which impacts serialization. Below you will find the link to Oracle Java Docs for more details.
想要定义几个点来突出影响序列化的更改。您可以在下方找到 Oracle Java Docs 的链接以了解更多详细信息。
Incompatible Changes
不兼容的变化
Incompatible changes to classes are those changes for which the guarantee of interoperability cannot be maintained. The incompatible changes that may occur while evolving a class are:
对类的不兼容更改是那些无法保证互操作性的更改。在进化一个类时可能发生的不兼容的变化是:
- Deleting fields
- Moving classes up or down the hierarchy
- Changing a nonstatic field to static or a nontransient field to transient
- Changing the declared type of a primitive field
- Changing the writeObject or readObject method so that it no longer writes or reads the default field data or changing it so that it attempts to write it or read it when the previous version did not.
- Changing a class from Serializable to Externalizable or vice versa.
- Changing a class from a non-enum type to an enum type or vice versa.
- Removing either Serializable or Externalizable.
- Adding the writeReplace or readResolve method to a class, if the behavior would produce an object that is incompatible with any older version of the class.
- 删除字段
- 在层次结构中向上或向下移动类
- 将非静态字段更改为静态或将非瞬态字段更改为瞬态
- 更改原始字段的声明类型
- 更改 writeObject 或 readObject 方法,使其不再写入或读取默认字段数据,或更改它以尝试写入或读取它,而以前的版本没有。
- 将类从 Serializable 更改为 Externalizable,反之亦然。
- 将类从非枚举类型更改为枚举类型,反之亦然。
- 删除 Serializable 或 Externalizable。
- 将 writeReplace 或 readResolve 方法添加到类,如果该行为会产生与该类的任何旧版本不兼容的对象。
Link from where the above information is taken http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html#6678
获取上述信息的链接 http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html#6678