当Eclipse在Eclipse中实现Serializable时,我有两个选择:添加默认serialVersionUID(1L)
或生成serialVersionUID(3567653491060394677L)
。我认为第一个更酷,但很多时候我看到有人使用第二个选项。是否有任何理由生成long serialVersionUID
?为什么生成long serialVersionUID而不是简单的1L?
回答
据我所知,这将是只是为了与以前版本的兼容性。这只会在你以前忽略使用serialVersionUID时才有用,然后做了一个你知道应该是compatible但是会导致序列化中断的改变。
有关详细信息,请参阅Java Serialization Spec。
序列化版本UID的目的是跟踪不同版本的一类,以进行物体的有效序列化。
这个想法是生成一个对于某个特定版本的类是唯一的ID,当有新的细节添加到类中时,这个ID将被更改,例如新字段,这会影响序列化的结构目的。
总是使用相同的ID,例如1L
意味着将来如果类定义被改变,导致序列化对象的结构发生变化,那么尝试反序列化对象时很可能会出现问题。
如果省略了ID,Java将实际上是基于对象的字段计算的ID给你,但我相信这是一个昂贵的过程,所以提供一个手动将提高性能。
这里的是其中讨论的类序列化和版本文章链接夫妇:
的主要原因对于生成的一个将会使它与已经存在持久拷贝的类的现有版本兼容。
如果没有指定的serialVersionUID那么Java做一个对飞。生成的serialVersionUID就是这个数字。如果您更改了类中的某些内容,但这些内容并未真正使您的类与以前的序列化版本不兼容,而是更改了散列,则需要使用生成的非常大的serialVersionUID(或来自错误消息的“期望”编号) 。否则,如果你正在跟踪自己的一切,0,1,2 ...是更好的。
serialVersionUID
的“long”默认值是Java Serialization Specification定义的默认值,由默认序列化行为计算得出。因此,如果添加默认版本号,只要没有任何结构发生变化,您的类就会(更快)序列化,但如果您更改类(添加/删除字段),则必须注意,您还更新了序列号。
如果您不必是现有的比特流兼容,你可以把1L
那里,在需要时有新的变化增加版本。也就是说,当更改的类的默认序列化版本与旧类的默认版本不同时。
您绝对应该在每次定义 实现java.io.Serializable
的类时创建一个serialVersionUID。如果你不这样做,会自动为你创建一个 ,但这是不好的。自动生成的 的serialVersionUID是基于你的类的方法签名,所以 如果你改变你的类在将来新增的方法(例如), 反序列化类的“旧”版本将失败。下面是 可能发生:
- 创建类的第一个版本,没有确定 的serialVersionUID。
- 将您的课程实例序列化到持久存储;一个 serialVersionUID是为你自动生成的。
- 修改您的课程以添加新方法并重新部署您的应用程序。
- 尝试反序列化连载在步骤2中,但现在它失败(当它应该会成功)的情况下,因为它有一个 不同自动生成的serialVersionUID。
因为在很多情况下,默认ID不是唯一的。所以我们为创造独特的概念而创建id。
那么,serialVersionUID是“静态字段没有被序列化”的规则的一个例外。 ObjectOutputStream每次将serialVersionUID的值写入输出流。 ObjectInputStream将其读回,并且如果从流中读取的值与当前版本的类中的serialVersionUID值不一致,则会引发InvalidClassException。此外,如果在类中没有正式声明的serialVersionUID被序列化,编译器会自动添加一个基于类中声明的字段的值。
当您使用的serialVersionUID(1L),而不是生成的serialVersionUID(3567653491060394677L)你在说什么。
你是说,你是100%的信心,没有这将不会碰这个类有这个类的一个不兼容的串行版本的1
版本号系统,如果你能想到的任何借口了它的序列化版本历史未知,可能很难说有信心。在它的一生中,一个成功的课程将由许多人维护,生活在许多项目中,并驻留在许多系统中。
你可以为此苦恼。或者你可以玩彩票希望失败。如果您生成该版本,那么出现问题的可能性很小。如果你认为“嘿,我打赌没有人用过1”,你的可能性比微小的更大。正是因为我们都认为0和1很酷,所以你有更高的击球几率。
-
当您生成的serialVersionUID(3567653491060394677L),而不是使用的serialVersionUID(1L)你说什么。
你是说的人可能有手动创建或超过这个类的历史生成的其他版本号和你不在乎,因为多头被吓坏大的数字。
无论哪种方式,除非你完全知道版本号在那里有整个宇宙序列化的类时所使用的历史或将永远存在,你正在做的机会。如果你有足够的时间让100%确定1是AOK,那就去做吧。如果这需要很多工作,请继续并盲目生成号码。你更有可能赢得彩票而不是出错。如果有,请告诉我,我会给你买一瓶啤酒。
这一切的谈话打我可能给你的serialVersionUID是随机生成的印象彩票。事实上,只要数字的范围均匀分布在Long的每个可能的值上,那都可以。但是,它实际上已经完成了这种方式:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
你与得到的唯一区别是你不需要的乱源。你正在使用类本身的改变来改变结果。但根据鸽子的原理,它仍然有可能出错并发生碰撞。这是非常不可能的。所以祝你好运,让我喝一杯啤酒。
然而,即使这个类仅会生活在一个系统和一个代码库,以为用手递增数给你的机会为零的冲突只是意味着你不明白的人。 :)
- 1. 在servlet中是什么意思(private static final long serialVersionUID = 1L)?
- 2. 为什么jvm生成serialVersionUID?
- 3. 为什么serialVersionUID的类型为Serializable类的long类型
- 4. 什么是C中的“-1L”?
- 5. 如何为Serializable生成serialVersionUID?
- 6. 为什么不是common_type <long,unsigned long> :: type = long long?
- 7. Java:为什么“long”原始类型不接受简单数字?
- 8. 为什么PostgreSQL“SequenceGenerator”,而不是“IdentityGenerator”的Hibernate默认生成器?
- 9. 为什么System.Buffer.BlockCopy采用int而不是long?
- 10. 为什么在使用Long而不是Integer时会出现ClassCastException?
- 11. 为什么var会以Double而不是Long来解析?
- 12. 为什么Linq2SQL生成嵌套查询而不是使用JOIN?
- 13. 在IntelliJ中为Kotlin类生成SerialVersionUID
- 14. 为什么没有为这些ATL简单对象生成ProgId?
- 15. 在Java中生成折线图的简单方法是什么?
- 16. 什么是从文本生成关键字的简单方法?
- 17. 什么是生成DOC文件的最简单方法?
- 18. 在C++中生成xml最简单的方法是什么?
- 19. 生成此UI的最简单方法是什么?
- 20. NumPy按位“和”失败int32&long,但不是long&int32;为什么?
- 21. 为什么双击而不是单个?
- 22. 为什么不使用简单的jquery事件而不是kendo window.observable?
- 23. 为什么Prelude的单词功能不是简单的书写?
- 24. 什么是Java类型long long
- 25. 为什么lst.add(2)为ArrayList <Long>给出编译错误而不是调用add(Long)方法?
- 26. 为什么我只使用ASP.NET MVC而不是简单的ASP.NET应用程序
- 27. 为什么大家都用双引号而不是简单的引号?
- 28. 为什么使用http(s)+ comet而不是简单的套接字编程?
- 29. 为什么Angular 2在路由中使用Observable而不是简单的数组?
- 30. 为什么使用VBO和/或IBO而不是简单的顶点数据?
这是如何重复?我不问为什么生成它,但为什么生成long serialVersionUID。 – IAdapter 2009-05-20 14:43:42
当乔恩斯基特使用的serialVersionUID,他用0L:http://stackoverflow.com/questions/605828/does-it-matter-what-i-choose-for-serialversionuid-when-extending-serializable-cla/605832#605832 ;) – 2009-10-05 13:19:14
@HannoFietz:确切的句子是:“为了简单起见,我建议**开始** 0和**每次你需要增加1 **。”所以,这听起来像他最初只使用'0L'。 – 2012-12-20 10:03:50