当类在Eclipse中实现Serializable时,我有两个选择:添加default serialVersionUID(1L)
或generate serialVersionUID(3567653491060394677L)
。我认为第一个比较酷,但是很多时候我看到人们在使用第二个选项。有什么理由产生long serialVersionUID
吗?
0L
只是刚开始使用。
当类在Eclipse中实现Serializable时,我有两个选择:添加default serialVersionUID(1L)
或generate serialVersionUID(3567653491060394677L)
。我认为第一个比较酷,但是很多时候我看到人们在使用第二个选项。有什么理由产生long serialVersionUID
吗?
0L
只是刚开始使用。
Answers:
序列化版本UID的目的是跟踪类的不同版本,以便执行对象的有效序列化。
这个想法是生成一个类的特定版本所独有的ID,然后在类中添加了新细节(例如会影响序列化对象结构的新字段)时更改该ID。
始终使用相同的ID,例如,这1L
意味着在将来,如果更改类定义而导致序列化对象的结构发生更改,则在尝试反序列化对象时很可能会出现问题。
如果省略ID,Java实际上会根据对象的字段为您计算ID,但是我认为这是一个昂贵的过程,因此手动提供一个ID可以提高性能。
这里有一些链接,这些链接讨论了类的序列化和版本控制:
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
使用默认serialVersionUID的主要原因 。以上注释摘自Java Object Serialization Specification版本6.0
生成该类的主要原因是使其与已经保留了副本的类的现有版本兼容。
每次定义实现的类时,绝对应该创建一个serialVersionUID java.io.Serializable
。如果您不这样做,将自动为您创建一个,但这很不好。自动生成的serialVersionUID是基于类的方法签名的,因此,如果以后更改类以添加方法(例如),则反序列化该类的“旧”版本将失败。这是可能发生的情况:
如果您未指定serialVersionUID,则Java会即时生成一个。生成的serialVersionUID是该数字。如果您更改了您的类中的某些内容,但实际上并没有使您的类与先前的序列化版本不兼容,而是更改了哈希,那么您需要使用生成的非常大的serialVersionUID(或错误消息中的“预期”数字) 。否则,如果您自己跟踪所有内容,则0、1、2 ...更好。
当您使用serialVersionUID(1L)而不是生成serialVersionUID(3567653491060394677L)时,您在说什么。
您是在说您有100%的信心,没有哪个系统会碰到该类的,具有不兼容的序列化版本且版本号为1的此类。
如果您能为它的序列化版本历史记录不明找到任何借口,那么可能很难说出来。在它的一生中,成功的课程将由许多人维护,并存在于许多项目中,并存在于许多系统中。
您可以为此感到痛苦。或者您可以玩彩票,希望输掉。如果生成该版本,则极有可能出现问题。如果您假设“嘿,我敢打赌,没有人用过1”,则您的赔率大于微小的赔率。正是因为我们都认为0和1很酷,所以您击中它们的几率更高。
--
当您生成serialVersionUID(3567653491060394677L)而不是使用serialVersionUID(1L)时,您在说什么。
您说的是人们可能在此类的历史记录中手动创建或生成了其他版本号,因此您不必理会,因为Longs迷恋着大量的数字。
无论哪种方式,除非您完全了解在类已经存在或将要存在的整个宇宙中序列化该类时使用的版本号的历史,否则您将是一个机会。如果您有时间确保100%确保1是AOK,请继续。如果要做很多工作,请继续盲目生成数字。您比中奖更有可能赢得彩票。如果是这样,请告诉我,我会给您买啤酒。
经过所有关于彩票的讨论,我可能给您的印象是serialVersionUID是随机生成的。实际上,只要数字范围均匀地分布在Long的每个可能值上就可以了。但是,实际上是这样进行的:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
您获得的唯一区别是您不需要随机来源。您正在使用类本身的更改来更改结果。但是根据鸽洞原理,它仍然有可能出错并发生碰撞。这是极不可能的。祝我好运。
但是,即使该类只能在一个系统和一个代码库中生活,也认为手工增加数量会给您带来零碰撞的机会,这仅意味着您不了解人类。:)
序列化版本UID的目的是跟踪类的不同版本,以便执行对象的有效序列化。
这个想法是生成一个类的特定版本所独有的ID,然后在类中添加了新细节(例如会影响序列化对象结构的新字段)时更改该ID。
简单说明:
您要序列化数据吗?
序列化基本上是将类数据写入文件/流/等。反序列化将数据读回到类中。
您打算投产吗?
如果您只是用不重要/伪造的数据进行测试,则不必担心(除非您直接测试序列化)。
这是第一个版本吗?
如果是这样,请设置serialVersionUID = 1L。
这是第二,第三等产品版本吗?
现在,您需要担心serialVersionUID,并应对其进行深入研究。
基本上,如果在更新需要写入/读取的类时未正确更新版本,则在尝试读取旧数据时会出现错误。