JavaRush /Java 博客 /Random-ZH /为什么在 Java 中的 Serialized 类中使用 SerialVersionUID
0xFF
第 9 级
Донецк

为什么在 Java 中的 Serialized 类中使用 SerialVersionUID

已在 Random-ZH 群组中发布
Serialization对于许多 Java 开发人员来说SerialVersionUID始终是个谜。我经常看到关于什么是 的问题SerialVersionUID,或者如果我不在SerialVersionUID我的类中声明会发生什么Serializable为什么在 Java 中的 Serialized 类中使用 SerialVersionUID - 1除了令人困惑和不经常使用之外,这个问题的另一个原因是 Eclipse IDE 缺少警告SerialVersionUID,例如:“ Serialized 类 Customer 没有声明long类型Serializable的static Final SerialVersionUID 字段”long“)。在本文中,您不仅将了解 Java 的基础知识,还将了解它对序列化和反序列化过程的影响。当您声明一个类(如通过实现令牌接口)时,Java 运行时将使用默认序列化机制在磁盘上存储该类的实例,除非您将进程配置为使用Externalized 接口。在序列化期间,Java 运行时会为该类创建一个版本号,以便稍后可以对其进行反序列化。在 Java 中,该版本号称为. 如果在反序列化期间没有匹配,则进程将退出并在“ ”流中出现异常,并且还将打印类名和相应的. 解决此问题的快速解决方案是将其复制并定义为类中的类型常量。在这篇文章中,我们将了解为什么要在Java中使用以及如何使用JDK的serialver工具来生成这个ID。如果您是序列化新手,您还可以观看Top 10 Java Serialization Interview Questions来评估您的知识并找到您理解中的差距以供进一步阅读。与(并发)和(多线程)一样,(序列化)是另一个值得阅读多次的主题。 CustomerSerialVersionUIDSerialVersionUIDSerializablejava.io.SerializableSerialVersionUIDSerialVersionUIDInvalidClassExceptionmainjava.io.InvalidClassExceptionSerialVersionUIDSerialVersionUIDprivate static final longSerialVersionUIDConcurrencyMulti-threadingSerialization

为什么在 Java 中使用 SerialVersionUID

正如我所说,当我们没有在类中定义值时,序列化机制将为我们做这件事SerialVersionUIDstatic final long这种机制对许多细节都很敏感,包括类的字段、它们的访问修饰符、它实现的接口,甚至不同的编译器实现;对类的任何更改或使用不同的编译器都可能产生不同的结果,SerialVersionUID这最终将导致阻止序列化数据被重新加载。依赖Java的序列化机制来生成这个id是有风险的,这就是为什么SerialVersionUID在你的Serialized类中显式定义它是一个好主意。我强烈建议阅读 Java 经典著作 - Joshua Bloch 《Effective Java》,以了解 Java 序列化以及错误处理它们的问题。对了,JDK还提供了一个工具serialver,位于JAVA_HOME目录的bin目录下,在我的电脑上是C:\Program Files\Java\jdk1.6.0_26\bin\serialver.exe,可以用来生成对于旧课程。如果您对类进​​行的更改破坏了序列化并且您的应用程序无法重新加载序列化实例,则这非常有用。您可以轻松地使用此实用程序来创建旧实例,然后通过将该字段声明为private static final long来显式使用它。顺便说一句,出于性能和安全原因,强烈建议使用常规二进制格式进行序列化;同样,“Effective Java”有几个段落非常详细地演示了常规格式的优点。 SerialVersionUIDSerialVersionUID SerialVersionUID

如何使用serialver JDK实用程序生成SerialVersionUID

您可以使用serialver来生成SerialVersionUID类。这对于开发类特别有用;该实用程序SerialVersionUID以易于复制的格式返回。您可以使用serialverJDK 实用程序,如示例所示:
$ serialver
use: serialver [-classpath classpath] [-show] [classname...]
$ serialver -classpath . Hello
Class Hello is not Serializable.
$ serialver -classpath . Hello
Hello: static final long SerialVersionUID = -4862926644813433707L;
您还可以使用该实用程序serialver作为GUI命令$ serialver –show,这将打开一个检查器serial version,该检查器获取完整的类名并显示它Serial version

概括

现在我们知道它是什么SerialVersionUID以及为什么在类中声明它很重要Serializable,是时候回顾一下与 Java SerialVersionUID 相关的一些重要事实了。
  1. SerialVersionUID用于指示序列化数据的版本。

  2. 当我们不在SerialVersionUID类中声明时,Java运行时会为我们做这件事,但是这个过程对类的许多元数据敏感,包括字段数量、字段类型、字段访问修饰符、类中实现的接口等。您可以在 Oracle 的序列化文档中找到确切的信息。

  3. 建议将 SerialVersionUID 声明为 private static final long 变量以避免默认机制。如果您忘记了这一点,某些 IDE(例如Eclipse)也会发出警告,例如:“Serialized 类 Customer 未声明 long 类型的静态最终 SerialVersionUID 字段。”。尽管您可以通过转到“窗口”>“首选项”>“Java”>“编译器”>“错误/警告”>“潜在编程问题”来禁用此警告,但我建议不要这样做。只有不需要数据恢复的时候我才可以大意。这是这个错误在 Eclipse IDE 中的样子,您所需要做的就是快速做出第一个决定。 为什么在 Java 中的 Serialized 类中使用 SerialVersionUID - 2

  4. 您还可以使用 JDK 中的 Serialver 实用程序为 Java 中的类生成串行版本。该实用程序还有一个 GUI,在传递 - 参数时启用show

  5. 序列化的最佳实践是显式声明SerialVersionUID, 以避免反序列化出现任何问题,特别是当您使用依赖于序列化数据的客户端-服务器应用程序(例如 RMI)时。
这都是关于SerialVersionUIDJava 的。现在我们知道为什么在课堂上正确声明很重要SerialVersionUID。您可以感谢 IDE 的提醒,这可能会破坏您的类的反序列化。如果您想了解有关序列化和相关概念的更多信息,您还可以查看这些精彩的文章。 原创在这里
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION