使用 seralVersionUID 还是禁止显示警告?

我想创建一个类,例如,扩展 HttpServlet?我的编译器警告我,我的类应该有一个 serialVersionUID。如果我知道这个对象永远不会被序列化,我应该定义它还是添加一个注释来抑制这些警告?

你会怎么做,为什么?

34913 次浏览

让 Eclipse 生成一个 ID。快速简单。警告不容忽视。如果到了对象/必须/被序列化的地步,还可以省去很多麻烦。

如果不打算序列化实例,请添加 SuppressPolice。

生成的序列 ID 可能有点危险。它表明您故意给它一个序列号,并保存序列化和反序列化。在更新的应用程序版本中更改类时,很容易忘记更新序列号。如果类字段已更改,则反序列化将失败。使用 SuppressPolice 至少可以告诉代码的读者您并不打算序列化这个类。

我不知道 Java 的最佳实践,但我突然想到,如果你声称序列化永远不会发生,你可以添加一个 writeObject 方法。然后压制警告,安全地知道它不可能适用于你。

否则,将来可能会有人通过父类序列化您的对象,并最终得到默认的序列化表单,其中:

  • 表单在代码的不同版本之间不兼容。
  • 你压制了这种情况的警告。

添加 ID 听起来像是一种混乱,因为您真正想做的不是序列化。期望调用方不序列化您的对象意味着您期望它们“知道”它们的 HttpServlet 属于您的类。如果您拥有一个不能序列化的可序列化对象,那么多态性的缺陷就会发生在您的头上,至少您可以确保粗心的调用者知道这一点。

这个警告快把我逼疯了,因为每次你子类化一个 Swing 类,你 知道永远不会序列化它,但是有一个愚蠢的警告。但没错,我让 Eclipse 生成了一个。

我拒绝被 Eclipse 吓得在我的代码中添加混乱!

我只是将 Eclipse 配置为不生成关于丢失 serialVersionUID 的警告。

即使您知道这个对象将被序列化,也不需要生成 seralVersionUID,因为 java 将自动为您生成它,并自动跟踪更改,所以您的序列化将始终工作正常。只有当您知道自己在做什么(向后序列化兼容性、手动更改跟踪等等)时,才应该生成它

所以我认为,在大多数情况下,压制警告是最好和最安全的解决方案。

如果省略了 seralVersionUID,java 将在编译时为该类生成一个(它随着每次编译而变化)。

在反序列化对象时,将反序列化对象的 seralVersionUID 与 jvm 中的类的 seralVersionUID 进行比较。如果它们不同,则认为它们不兼容,并引发异常。例如,在升级程序和反序列化旧类之后就会发生这种情况。

我总是使用1L 作为 seralversionUID。它不会造成损害(与生成的默认值相比) ,并且它仍然留下了以后通过增加 id 来破坏兼容性的选项。

将 SVUID 生成到实现串行化的 每个类是有益的。原因很简单。你 永远不会知道什么时候它将由你或某些第三方序列化。可以配置许多将序列化 servlet 的服务。对于每个 IDE 存在的插件生成一个或只使用模板和设置 svuid = 1L。

谢谢@Steve Jessop 对这个问题的回答,只需要5行代码... ... 一点也不麻烦。

我把 @SuppressWarnings("serial")添加到了问题类的正上方。

我还添加了这种方法:

private void writeObject(ObjectOutputStream oos) throws IOException {
throw new IOException("This class is NOT serializable.");
}

希望这就是史蒂夫的意思:)

看情况。

如果使用不同的编译器多次编译源代码,则编译后的代码可能具有不同的序列化 ID,这将中断序列化。然后,您需要在代码中显式地使用常量 seralizationId。它必须是静态的、最终的和每个类(不可继承)。

然而,如果你总是用一个特定的编译器编译你的代码,并且总是一次性地将你的代码部署到所有的虚拟机中,你可能需要严格的版本检查,并且想要确保任何时候只有一个版本的代码在运行,在这种情况下,你应该只是禁止警告。因此,如果 VM 没有成功部署,并且正在运行旧版本的代码,那么在序列化过程中可能会出现异常,而不是奇怪的反序列化对象。这正好是我的情况,我们过去有一个非常非常大的集群,我们需要严格的版本检查来发现任何部署问题。

无论如何,你应该尽可能避免序列化,因为默认的序列化与协议缓冲或者节俭相比非常慢,而且不支持跨语言的互操作性。

如果您知道应用程序从不序列化事物,请在应用程序范围内禁止显示警告。这可以通过使用 javac 命令行参数来实现:

javac -Xlint -Xlint:-serial *******

这样你就会有除了“系列”以外的所有警告。 IDE 和像 Maven/SBT/Gradle 这样的构建工具可以很好地处理这个问题。