为什么生成长serialVersionUID而不是简单的1L?

发布于 2024-07-19 21:34:41 字数 212 浏览 10 评论 0原文

当类在 Eclipse 中实现 Serialized 时,我有两个选择:添加默认的 serialVersionUID(1L) 或生成的 serialVersionUID(3567653491060394677L)。 我认为第一个选项更酷,但很多时候我看到人们使用第二个选项。 有什么理由生成长serialVersionUID吗?

When class implements Serializable in Eclipse, I have two options: add default serialVersionUID(1L) or generated serialVersionUID(3567653491060394677L). I think that first one is cooler, but many times I saw people using the second option. Is there any reason to generate long serialVersionUID?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

鸢与 2024-07-26 21:34:41

序列化版本 UID 的目的是跟踪类的不同版本,以便执行对象的有效序列化。

这个想法是生成一个对于某个类的特定版本唯一的 ID,然后当类中添加新的详细信息(例如新字段)时,该 ID 会发生更改,这会影响序列化对象的结构。

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

如果省略 ID,Java 实际上会根据对象的字段为您计算 ID,但我相信这是一个昂贵的过程,因此手动提供 ID 会提高性能。

以下是一些讨论类的序列化和版本控制的文章链接:

The purpose of the serialization version UID is to keep track of different versions of a class in order to perform valid serialization of objects.

The idea is to generate an ID that is unique to a certain version of an class, which is then changed when there are new details added to the class, such as a new field, which would affect the structure of the serialized object.

Always using the same ID, such as 1L means that in the future, if the class definition is changed which causes changes to the structure of the serialized object, there will be a good chance that problems arise when trying to deserialize an object.

If the ID is omitted, Java will actually calculate the ID for you based on fields of the object, but I believe it is an expensive process, so providing one manually will improve performance.

Here's are a couple of links to articles which discuss serialization and versioning of classes:

太阳哥哥 2024-07-26 21:34:41

据我所知,这只是为了与以前的版本兼容。 仅当您之前忽略使用serialVersionUID,然后进行了您知道应该是 兼容 但这会导致序列化中断。

有关更多详细信息,请参阅 Java 序列化规范

As far as I can tell, that would be only for compatibility with previous releases. This would only be useful if you neglected to use a serialVersionUID before, and then made a change that you know should be compatible but which causes serialization to break.

See the Java Serialization Spec for more details.

无所的.畏惧 2024-07-26 21:34:41

生成的主要原因是使其与已经具有持久副本的类的现有版本兼容。

The main reason for the generated one would be to make it compatible with an existing version of the class that already has persisted copies.

琴流音 2024-07-26 21:34:41

你绝对应该在每次定义时创建一个serialVersionUID
一个实现java.io.Serialized的类。 如果你不这样做,就会有人
会自动为您创建,但这很糟糕。 自动生成的
SerialVersionUID 基于类的方法签名,因此
如果您将来更改类以添加方法(例如),
反序列化该类的“旧”版本将会失败。 这是什么
可能发生的情况:

  1. 创建类的第一个版本,而不定义
    串行版本UID。
  2. 将类的实例序列化到持久存储; A
    系统会自动为您生成serialVersionUID。
  3. 修改您的类以添加新方法,然后重新部署您的应用程序。
  4. 尝试反序列化步骤 2 中序列化的实例,但现在失败了(当它应该成功时),因为它有一个
    不同的自动生成的serialVersionUID。

You absolutely should create a serialVersionUID every time you define
a class that implements java.io.Serializable. If you don't, one will
be created for you automatically, but this is bad. The auto-generated
serialVersionUID is based on the method signatures of your class, so
if you change your class in the future to add a method (for example),
deserializing the "old" versions of the class will fail. Here's what
can happen:

  1. Create the first version of your class, without defining the
    serialVersionUID.
  2. Serialize an instance of your class to a persistent store; a
    serialVersionUID is automatically generated for you.
  3. Modify your class to add a new method, and redeploy your application.
  4. Attempt to deserialize the instance that was serialized in step 2, but now it fails (when it should succeed), because it has a
    different auto-generated serialVersionUID.
一百个冬季 2024-07-26 21:34:41

serialVersionUID 的“长”默认值是由 Java 序列化规范,根据默认序列化行为计算。

因此,如果您添加默认版本号,只要结构上没有任何更改,您的类就会更快地(反)序列化,但您必须注意,如果您更改类(添加/删除字段),您也会更新序列号。

如果您不必兼容现有的比特流,您可以将 1L 放在那里,并在发生变化时根据需要增加版本。 也就是说,更改后的类的默认序列化版本与旧类的默认版本不同。

The "long" default of the serialVersionUID is the default value as defined by the Java Serialization Specification, calculated from the default serialization behaviour.

So if you add the default version number, your class will (de-)serialize faster as long as nothing has structurally changed, but you'll have to take care that if you change the class (add/remove fields) you also update the serial number.

If you do not have to be compatible to existing bit streams, you can just put 1L there and increment the version as needed when something changes. That is, when the default serialisation version of the changed class would be different from the default version of the old class.

心的憧憬 2024-07-26 21:34:41

如果您没有指定serialVersionUID,那么Java 会即时创建一个。 生成的serialVersionUID就是该数字。 如果您更改类中的某些内容并没有真正使您的类与以前的序列化版本不兼容,但更改了哈希值,那么您需要使用生成的非常大的数字serialVersionUID(或错误消息中的“预期”数字) 。 否则,如果您自己跟踪所有内容,那么 0、1、2... 会更好。

If you don't specify a serialVersionUID then Java makes one on the fly. The generated serialVersionUID is that number. If you change something in your class that doesn't really make your class incompatible with previous serialized verisons but changes the hash, then you need to use the generated very-large-number serialVersionUID (or the "expected" number from the error message). Otherwise, if you are keeping track of everything yourself, 0, 1, 2... is better.

莫多说 2024-07-26 21:34:41

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

唯一的区别是您不需要随机源。 您正在使用类本身的更改来更改结果。 但根据鸽巢原理,仍然有可能出错并发生碰撞。 这实在是太不可能了。 祝我好运,从我身上得到一杯啤酒。

然而,即使该类只存在于一个系统和一个代码库中,认为手动增加数字使冲突的可能性为零就意味着您不理解人类。 :)

When you use serialVersionUID(1L) rather than generating serialVersionUID(3567653491060394677L) you are saying something.

You are saying that you are 100% confident that no system that will ever touch this class that has an incompatible serialized version of this class with a version number of 1.

If you can think of any excuse for it's serialized version history to be unknown, that might be hard to say with confidence. In it's lifetime, a successful class will be maintained by many people, live in many projects, and reside in many systems.

You can agonize over that. Or you can play the lottery hoping to lose. If you generate the version you have a tiny chance of things going wrong. If you assume "Hey I bet no one used 1 yet" your odds are larger than tiny. It's precisely because we all think 0 and 1 are cool that you have higher odds of hitting them.

-

When you generate serialVersionUID(3567653491060394677L) rather than use serialVersionUID(1L) you are saying something.

You are saying people may have either manually created or generated other version numbers over the history of this class and you don't care because Longs are freaking big numbers.

Either way unless you perfectly know the history of version numbers used when serializing the class in the entire universe of where it has or will ever exist, you're taking a chance. If you have the time to make 100% sure 1 is AOK, go for it. If that's to much work, go ahead and blindly generate the number. You're more likely to win the lottery than to have that go wrong. If it does, let me know and I'll buy you a beer.

With all this talk of playing the lottery I may have given you the impression that serialVersionUID is generated randomly. In fact as long as the range of numbers is evenly distributed over every possible value of a Long that would be fine. However, it's actually done this way:

http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100

The only difference you get with that is you don't need a source of random. You're using the changes in class itself to change the result. But according to the pigeonhole principle there is still a chance it could go wrong and have a collision. It's just incredibly unlikely. So good luck getting a beer out of me.

However, even if the class will only ever live in one system and one code base, thinking that incrementing the number by hand gives you zero chance of collisions just means you don't understand humans. :)

猫性小仙女 2024-07-26 21:34:41

嗯,serialVersionUID 是“静态字段不被序列化”规则的一个例外。 ObjectOutputStream 每次将serialVersionUID 的值写入输出流。 ObjectInputStream 读回它,如果从流中读取的值与当前版本的类中的serialVersionUID 值不一致,则会抛出 InvalidClassException。 此外,如果要序列化的类中没有正式声明的serialVersionUID,编译器会自动添加根据类中声明的字段生成的值。

Well, serialVersionUID is an exception to the rule that “static fields don’t get serialized”. ObjectOutputStream writes every time the value of serialVersionUID to the output stream. ObjectInputStream reads it back and if the value read from the stream does not agree with the serialVersionUID value in the current version of the class, then it throws the InvalidClassException. Moreover, if there is no serialVersionUID officially declared in the class to be serialized, compiler automatically adds it with a value generated based on the fields declared in the class.

仙女山的月亮 2024-07-26 21:34:41

为了添加@David Schmitts 的答案,根据经验,我将始终使用默认的 1L 不符合惯例。 我只需要返回并更改其中一些值几次,但当我进行更改并每次将默认数字更新为 1 时,我就知道这一点。

在我目前的公司,他们需要自动生成的号码,因此我将其用于约定,但我更喜欢默认值。 我的看法是,如果这不是您工作的约定,请使用默认值,除非您认为由于某种原因会不断更改序列化类的结构。

To add to @David Schmitts answer, as a rule of thumb I would always use the default 1L out of convention. I've only had to go back and change some of them a few times, but I knew that when I made the change and updated the default number by one each time.

At my current company they require the auto-generated number so I use that for convention, but I prefer the default. My take is, if it's not a convention where you work, use the default, unless you think you will be constantly changing the structure of you serialized classes for some reason.

故事灯 2024-07-26 21:34:41

因为很多情况下默认的id并不是唯一的。 所以我们创建 id 来制作独特的概念。

Because in many cases default id is not unique. so we create id for making unique concept.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文