2009-05-20 80 views
181

当Eclipse在Eclipse中实现Serializable时,我有两个选择:添加默认serialVersionUID(1L)或生成serialVersionUID(3567653491060394677L)。我认为第一个更酷,但很多时候我看到有人使用第二个选项。是否有任何理由生成long serialVersionUID为什么生成long serialVersionUID而不是简单的1L?

+41

这是如何重复?我不问为什么生成它,但为什么生成long serialVersionUID。 – IAdapter 2009-05-20 14:43:42

+12

当乔恩斯基特使用的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

+5

@HannoFietz:确切的句子是:“为了简单起见,我建议**开始** 0和**每次你需要增加1 **。”所以,这听起来像他最初只使用'0L'。 – 2012-12-20 10:03:50

回答

78

据我所知,这将是只是为了与以前版本的兼容性。这只会在你以前忽略使用serialVersionUID时才有用,然后做了一个你知道应该是compatible但是会导致序列化中断的改变。

有关详细信息,请参阅Java Serialization Spec

60

序列化版本UID的目的是跟踪不同版本的一类,以进行物体的有效序列化。

这个想法是生成一个对于某个特定版本的类是唯一的ID,当有新的细节添加到类中时,这个ID将被更改,例如新字段,这会影响序列化的结构目的。

总是使用相同的ID,例如1L意味着将来如果类定义被改变,导致序列化对象的结构发生变化,那么尝试反序列化对象时很可能会出现问题。

如果省略了ID,Java将实际上是基于对象的字段计算的ID给你,但我相信这是一个昂贵的过程,所以提供一个手动将提高性能。

这里的是其中讨论的类序列化和版本文章链接夫妇:

+44

使用1L背后的​​想法是,每次更改类属性或方法时都会增加它。 – Powerlord 2009-05-20 14:47:42

+0

谢谢你的信息:) – coobird 2009-05-20 14:51:31

+35

有允许自动生成的serialVersionUID没有运行时性能的影响 - 它是由javac的在编译时产生的......如果你反编译的类的字节码,你会真正看到的静态变量中字节码。 – Jared 2009-05-20 18:58:00

17

的主要原因对于生成的一个将会使它与已经存在持久拷贝的类的现有版本兼容。

6

如果没有指定的serialVersionUID那么Java做一个对飞。生成的serialVersionUID就是这个数字。如果您更改了类中的某些内容,但这些内容并未真正使您的类与以前的序列化版本不兼容,而是更改了散列,则需要使用生成的非常大的serialVersionUID(或来自错误消息的“期望”编号) 。否则,如果你正在跟踪自己的一切,0,1,2 ...是更好的。

12

serialVersionUID的“long”默认值是Java Serialization Specification定义的默认值,由默认序列化行为计算得出。因此,如果添加默认版本号,只要没有任何结构发生变化,您的类就会(更快)序列化,但如果您更改类(添加/删除字段),则必须注意,您还更新了序列号。

如果您不必是现有的比特流兼容,你可以把1L那里,在需要时有新的变化增加版本。也就是说,当更改的类的默认序列化版本与旧类的默认版本不同时。

9

您绝对应该在每次定义 实现java.io.Serializable的类时创建一个serialVersionUID。如果你不这样做,会自动为你创建一个 ,但这是不好的。自动生成的 的serialVersionUID是基于你的类的方法签名,所以 如果你改变你的类在将来新增的方法(例如), 反序列化类的“旧”版本将失败。下面是 可能发生:

  1. 创建类的第一个版本,没有确定 的serialVersionUID。
  2. 将您的课程实例序列化到持久存储;一个 serialVersionUID是为你自动生成的。
  3. 修改您的课程以添加新方法并重新部署您的应用程序。
  4. 尝试反序列化连载在步骤2中,但现在它失败(当它应该会成功)的情况下,因为它有一个 不同自动生成的serialVersionUID。
0

因为在很多情况下,默认ID不是唯一的。所以我们为创造独特的概念而创建id。

1

那么,serialVersionUID是“静态字段没有被序列化”的规则的一个例外。 ObjectOutputStream每次将serialVersionUID的值写入输出流。 ObjectInputStream将其读回,并且如果从流中读取的值与当前版本的类中的serialVersionUID值不一致,则会引发InvalidClassException。此外,如果在类中没有正式声明的serialVersionUID被序列化,编译器会自动添加一个基于类中声明的字段的值。

3

当您使用的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

你与得到的唯一区别是你不需要的乱源。你正在使用类本身的改变来改变结果。但根据鸽子的原理,它仍然有可能出错并发生碰撞。这是非常不可能的。所以祝你好运,让我喝一杯啤酒。

然而,即使这个类仅会生活在一个系统和一个代码库,以为用手递增数给你的机会为零的冲突只是意味着你不明白的人。 :)

相关问题