Java 1L serialVersionUID 是什么意思?我什么时候可以使用这个默认值 1L?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21850907/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:02:43  来源:igfitidea点击:

What means 1L serialVersionUID? When could I use this default value 1L?

java

提问by Ying Style

There are 3 ways to define the serialVersionUID :

有 3 种方法可以定义 serialVersionUID:

1. private static final long serialVersionUID = 1L; (Default)
2. private static final long serialVersionUID = -8940196742313994740L; (Generated)
3. Don't define serialVersionUID and let the JVM define it at runtime. @Lance Java

But I don't understand the first way!

但我不明白第一种方式!

I have seen it already, that somebody defines "serialVersionUID=1L" for all java-classes in source code.

我已经看到了,有人为源代码中的所有 java 类定义了“serialVersionUID=1L”。

What is the meaning? Is that useful?

什么意思?那有用吗?

If all classes have the same serialVersionUID 1L, is there no problem?

如果所有类都有相同的serialVersionUID 1L,那没有问题吗?

回答by Marco Bolis

You can assign any longvalue to serialVersionUID, but you have to change it every time you modify your class.

您可以为 分配任何longserialVersionUID,但每次修改类时都必须更改它。

The second looks like a generated serialVersionUID, based on the features of the current class version.

第二个看起来像一个生成的serialVersionUID,基于当前类版本的特性。

回答by ravibagul91

This is explain here:

这是在这里解释:

The serialVersionUID is a universal version identifier for a Serializable class. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If no match is found, then an InvalidClassException is thrown.

serialVersionUID 是 Serializable 类的通用版本标识符。反序列化使用这个数字来确保加载的类与序列化的对象完全对应。如果未找到匹配项,则抛出 InvalidClassException。



From the javadoc:

javadoc

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:

序列化运行时将每个可序列化类与一个称为 serialVersionUID 的版本号相关联,在反序列化期间使用它来验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类。如果接收方为对象加载了一个与相应发送方类具有不同 serialVersionUID 的类,则反序列化将导致 InvalidClassException。一个可序列化的类可以通过声明一个名为“serialVersionUID”的字段来显式声明它自己的serialVersionUID,该字段必须是静态的、最终的和长类型的:



Useful Links

有用的链接

  1. java.io.Serializable
  2. Why should I bother about serialVersionUID? (StackOverflow)
  3. serialVersionUID in Java Serialization
  1. java.io.Serializable
  2. 为什么我要为 serialVersionUID 烦恼?(堆栈溢出)
  3. Java序列化中的serialVersionUID

回答by lance-java

The JVM will throw a InvalidClassExceptionif the serialVersionUIDof a serialized object does not match the serialVersionUIDof the class it is being deserialized as.

InvalidClassException如果serialVersionUID序列化对象serialVersionUID的 与它被反序列化的类的不匹配,JVM 将抛出。

The serialVersionUIDof a class should change every time the class changes in an incompatible way. Normally this means every time you change the shapeof a class (ie fields or methods change).

serialVersionUID一类的应该改变每类以不兼容的方式发生变化的时间。通常这意味着每次您更改shape类的(即字段或方法更改)。

There are some cases where you don't want the serialVersionUIDto change. For instance you might accept old versions of the object into your application. In this case, you can leave the serialVersionUIDthe same and new fields will come through as null.

在某些情况下,您不想serialVersionUID更改。例如,您可能会在应用程序中接受对象的旧版本。在这种情况下,您可以serialVersionUID保持不变,新字段将作为空值出现。

回答by sakura

The value is used while serializing an object and de-serializing the object back into JVM.

该值在序列化对象并将对象反序列化回 JVM 时使用。

Further, If your class changes and you don't want to support backward compatibility (i.e. able to de-serialize the object back which was serialized using your last version of class) you can change the version number to any other value.

此外,如果您的类发生更改并且您不想支持向后兼容性(即能够反序列化使用您的上一个版本的类序列化的对象),您可以将版本号更改为任何其他值。

However, to support the backward compatibility you need to keep the same version number as previously set value of serialVersionUID.

但是,为了支持向后兼容性,您需要保持与之前设置的 serialVersionUID 值相同的版本号。

The best practice is to change the serialVersionUID, every time you have some incompatible changes to the class.

最佳实践是在每次对类进行一些不兼容的更改时更改 serialVersionUID。

回答by Michael Borgwardt

What is the meaning? Is that useful?

什么意思?那有用吗?

Yes. The point of serialVersionUID is to give the programmer control over which versions of a class are considered incompatible in regard to serialization. As long as the serialVersionUID stays the same, the serialization mechanism will make a best effort to translate serialized instances, which may not be what you want. If you make a semantic change that renders older versions incompatible, you can change the serialVersionUID to make deserializing older instances fail.

是的。serialVersionUID 的目的是让程序员控制在序列化方面认为类的哪些版本不兼容。只要serialVersionUID保持不变,序列化机制就会尽最大努力翻译序列化实例,这可能不是你想要的。如果您进行语义更改导致旧版本不兼容,您可以更改 serialVersionUID 以使反序列化旧实例失败。

If all classes have the same serialVersionUID 1L, is there no problem?

如果所有类都有相同的serialVersionUID 1L,那没有问题吗?

No - the serialVersionUID is per class.

否 - serialVersionUID 是每个类

回答by NickJ

Imagine you write a class with a serialVersionUID, instantiate it, then serialize it to a file (with ObjectOutputStream)

想象一下你用 a 编写一个类serialVersionUID,实例化它,然后将它序列化到一个文件(使用 ObjectOutputStream)

Then you modify the class.

然后你修改类。

Then, with the modified class, you deserialize (read in) the version you serialized before modification. Java will check the serialVersionUIDof the current class and the serialized class, and if they don't match, the deserialization will fail. This is a deliberate fail-fast to prevent much more subtle (and harder to debug) errors occurring later on due to class version incompatibilities.

然后,使用修改后的类,反序列化(读入)修改前序列化的版本。Java 会检查serialVersionUID当前类和序列化后的类,如果不匹配,反序列化就会失败。这是一种刻意的快速失败,以防止稍后由于类版本不兼容而发生更微妙(并且更难调试)的错误。

If you omit serialVersionUIDthen you disable the version checking. If you alwaysset if to 1L, then the check will always pass (the value is always the same) so you are still vulnerable to subtle class version incompatibility problems.

如果省略,serialVersionUID则禁用版本检查。如果您始终将 if 设置为 1L,那么检查将始终通过(值始终相同),因此您仍然容易受到微妙的类版本不兼容问题的影响。

回答by Stephen C

Yes, I've seen code that defined serialVersionUIDlike that too. I think it is a bad idea.

是的,我也见过这样定义的代码serialVersionUID。我认为这是一个坏主意。

In this context there is only one "distinguished" value for the serialVersionUIDfield; i.e. zero ... 0L. Zero means "compute the version id at runtimeby applying the standard algorithm" based on the actual class that you are serializing / deserializing. That means that whenever your code's effective serialization signature changes, the serialization / deserialization code will use a different version id. From a (big picture) type safety perspective, this is the safest thing to do, though it is also somewhat inefficient, and protentially more fragile.

在这种情况下,该serialVersionUID字段只有一个“显着”值;即零... 0L。零表示基于您正在序列化/反序列化的实际类,“通过应用标准算法在运行时计算版本 ID ”。这意味着每当您的代码的有效序列化签名发生变化时,序列化/反序列化代码将使用不同的版本 ID。从(大图)类型安全的角度来看,这是最安全的做法,尽管它也有些低效,而且可能更脆弱。

What is the meaning?

什么意思?

The 1Lhas no special meaning. It is just a number that will match 1Las the "other" version id.

1L没有任何特殊含义。它只是一个1L与“其他”版本 ID匹配的数字。

To my mind, you are better off either using 0L, or a version number that was (at some point) generated using the standard algorithm.

在我看来,最好使用0L,或者使用标准算法(在某些时候)生成的版本号。

  • If you use 0L, then you get definite deserialization exceptions if classes change in ways that could be source of problems. If you needthis, it is a good thing.

  • On the other hand you use a generated version id, you (the programmer) can make your own decision about when to regenerate the id. And when you do decide to regenerate, the id will only change if the class signature haschanged. (If classes representation etc hasn't changed, the regenerated signature should be identical to the original one!) And when the id doeschange, you can think about whether to add custom methods ('readObject', etc) to deal with the incompatibility.

  • However, if you use 1L, you can't tell if the version id needs tochange without checking your code history, and comparing the old / new versions of the classes ... back as far as you need to.

  • 如果您使用0L,那么如果类以可能成为问题根源的方式更改,您将获得明确的反序列化异常。如果你需要这个,这是一件好事。

  • 另一方面,您使用生成的版本 id,您(程序员)可以自己决定何时重新生成 id。当您决定重新生成时,只有在类签名发生更改时,id 才会更改。(如果类表示等没有改变,重新生成的签名应该和原来的一样!)而当id发生变化时,你可以考虑是否添加自定义方法('readObject'等)来处理不兼容.

  • 但是,如果您使用1L,如果不检查您的代码历史记录并比较这些类的旧/新版本……您就无法判断是否需要更改版本 ID 。

Is that useful?

那有用吗?

It depends on what you consider "useful" to mean. If you think it is a good thing to hard wire the version id to "trust me, it is ok", then 1Lis useful.

这取决于您认为“有用”的含义。如果您认为将版本 ID 硬连接到“相信我,没关系”是一件好事,那么1L很有用。



My recollection is that some versions of Eclipse offer 1Las one of the possible auto-corrections for a missing serialVersionUIDfield warning. That is probable where the instances you see have come from.

我记得,某些版本的 Eclipse 提供1L了可能的自动更正功能之一,用于丢失serialVersionUID字段警告。这很可能是您看到的实例的来源。

回答by scottb

It's important to make clear the fact that having a class implement the Serializableinterface makes ALLfields not declared transientpart of the exported APIof the class, whether or not those fields are declared private.

重要的是要明确这样一个事实,即让类实现Serializable接口会使所有未声明的字段成为类transient导出 API的一部分,无论这些字段是否已声明private

In other words, implementing Serializable:

换句话说,实现可序列化:

  • breaks encapsulation. If the class has any chance to become a successful, long-lived class then you must support the serialized form ... forever.

  • can seriously impair your ability to evolve that class, precisely because it is a part of its exported API. The alternative is to break backward compatibility.

  • can create security problems for your class and its application. Deserialization represents a way for making Java objects without a constructor, so it's possible to violate a class's invariants by providing rogue byte streams to the deserialization facility.

  • 打破封装。如果该类有机会成为一个成功的、长期存在的类,那么您必须永远支持序列化形式。

  • 可能会严重削弱您发展该类的能力,正是因为它是其导出 API 的一部分。另一种方法是打破向后兼容性。

  • 可能会为您的类及其应用程序带来安全问题。反序列化代表了一种无需构造函数即可生成 Java 对象的方法,因此通过向反序列化工具提供恶意字节流可能会违反类的不变量。

The serialVerionUIDshould be thought of as a property of the serialized form. It is meant to convey to one JVM whether or not there a difference between the serialized form of a class instance that it is receiving and the serialized form of of that same class rendered (maybe) somewhere else.

serialVerionUID应被看作是对的属性序列化形式。它旨在向一个 JVM 传达它正在接收的类实例的序列化形式与在其他地方呈现(可能)的同一类的序列化形式之间是否存在差异。

You can see the potential problems that may occur if the serialized forms are different but the UIDs are the same. The receiving JVM will assume that the received serial form version between an old class and the new one are the same when they aren't and will dutifully go ahead and attempt to deserialize the byte stream.

您可以看到如果序列化形式不同但 UID 相同可能会出现的潜在问题。接收 JVM 将假定旧类和新类之间接收到的串行形式版本相同,而它们不同时将尽职尽责地继续尝试反序列化字节流。

TLDR: You shouldn't change the UID when you feel like it. You should change it when the serialized formof the class changes so that versions of software that use older versions of your class (with the different serialized form) will break instead of (possibly silently) doing the wrong thing. Not designing a good serialized form your classes will make it harder (even much harder) to provide backward compatibility for its clients. In the ideal case, the serialized form for a class persists throughout its entire evolution (and so its UID need never change).

TLDR:您不应该在需要时更改 UID。当类的序列化形式更改时,您应该更改它,以便使用旧版本的类(具有不同的序列化形式)的软件版本将中断,而不是(可能默默地)做错误的事情。不设计一个好的序列化形式,你的类将更难(甚至更难)为其客户端提供向后兼容性。在理想情况下,类的序列化形式在其整个演化过程中持续存在(因此其 UID 永远不会改变)。