72

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

你会做什么,为什么?

4

12 回答 12

30

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

否则,将来有人可能会通过父类序列化您的对象,并以默认的序列化形式结束,其中:

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

添加一个 ID 听起来像是一个麻烦,因为你真正想要做的不是序列化。期望调用者不序列化您的对象意味着您期望他们“知道”他们的 HttpServlet 何时属于您的类。由于拥有一个不能序列化的可序列化对象,多态性的破坏就在你的头上,你至少可以确保粗心的调用者知道它。

于 2008-09-28T21:12:12.807 回答
20

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

生成的序列号可能有点危险。它建议您故意给它一个序列号,并且可以保存序列化和反序列化。在更改了类的较新版本的应用程序中,很容易忘记更新序列号。如果类字段已更改,反序列化将失败。拥有 SuppressWarning 至少可以告诉读者您的代码您不打算序列化此类。

于 2008-09-28T20:58:12.450 回答
15

我拒绝被 Eclipse 恐吓而使我的代码变得混乱!

我只是将 Eclipse 配置为在缺少 serialVersionUID 时不生成警告。

于 2008-09-28T21:35:23.343 回答
12

感谢@Steve Jessop 对此的回答。这是 5 行代码......几乎没有什么麻烦。

@SuppressWarnings("serial")在有问题的班级上方添加了。

我还添加了这个方法:

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

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

于 2010-05-14T03:24:32.910 回答
6

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

所以我想说在大多数情况下抑制警告是最好和最安全的解决方案。

于 2008-09-28T21:55:46.417 回答
4

最好为每个实现可序列化的类生成 SVUID。原因很简单。你永远不知道它什么时候会被你或某个第 3 方序列化。可以配置许多将序列化 servlet 的服务。对于每个 IDE 存在的插件,它生成一个或只使用模板并设置 svuid = 1L。

于 2008-09-29T14:02:31.990 回答
3

这个警告让我发疯,因为每次你将 Swing 类子类化时,你都知道你永远不会序列化它,但是有那个愚蠢的警告。但是,是的,我让 Eclipse 生成一个。

于 2008-09-28T21:29:06.323 回答
2

让 Eclipse 生成一个 ID。快捷方便。警告不容忽视。如果您遇到对象 /has/ 被序列化的地步,也可以为您节省很多麻烦。

于 2008-09-28T20:52:52.837 回答
2

如果您遗漏了 serialVersionUID,java 将在编译时为该类生成一个(每次编译都会更改)。

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

我总是使用 1L 作为serialversionUID。它不会受到伤害(与默认生成的相比),并且它仍然保留稍后通过增加 id 来破坏兼容性的选项。

于 2008-09-29T09:59:41.620 回答
2

这取决于。

如果您使用不同的编译器多次编译源代码,则编译后的代码可能具有不同的序列化 ID,这会破坏序列化。然后,您需要在代码中明确地坚持一个常量 serializationId。它必须是静态的、最终的和每个类(不可继承)。

但是,如果您总是使用特定的编译器编译您的代码,并且总是一次性将您的代码部署到您的所有 VM,您可能需要严格的版本检查,并希望确保任何时候只有一个版本的代码在运行,在在这种情况下,你应该压制警告。因此,如果 VM 未成功部署并且正在运行旧版本的代码,您可能希望在序列化期间出现异常,而不是怪异的反序列化对象。这恰好是我的情况,我们曾经有一个非常大的集群,我们需要严格的版本检查来找出任何部署问题。

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

于 2011-06-08T02:48:21.517 回答
1

请点击此链接获取详细说明:http ://technologiquepanorama.wordpress.com/2009/02/13/what-is-use-of-serialversioid/

于 2009-03-17T17:23:22.380 回答
1

如果您知道您的应用程序从不序列化事物,请在应用程序范围内抑制警告。这可以使用 javac 命令行参数来完成:

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

这样,您将收到除“串行”之外的所有警告。IDE-s 和 Maven/SBT/Gradle 等构建工具可以正常工作。

于 2015-12-15T11:01:44.243 回答