我想创建一个类,例如,扩展HttpServlet?我的编译器警告我,我的类应该具有serialVersionUID。如果我知道该对象永远不会序列化,是否应该定义它或添加注释以禁止显示这些警告?
你会怎么做,为什么?
我想创建一个类,例如,扩展HttpServlet?我的编译器警告我,我的类应该具有serialVersionUID。如果我知道该对象永远不会序列化,是否应该定义它或添加注释以禁止显示这些警告?
你会怎么做,为什么?
serialVersionUID
。
Answers:
我不知道Java最佳实践,但是我想到如果您声称序列化将永远不会发生,则可以添加一个抛出的writeObject方法。然后,在可能无法应用警告的情况下,消除警告,确保安全。
否则,将来有人可能会通过父类对您的对象进行序列化,并最终得到默认的序列化形式,其中:
添加一个ID听起来像是一个大障碍,因为您真正想要做的是不序列化。期望调用者不要序列化您的对象意味着您希望他们的HttpServlet是您的类时“知道”。拥有一个不可以序列化的Serializable对象,对多态性的破坏就在您的头上,并且您要做的至少是确保粗心的调用者知道它。
我拒绝被Eclipse吓倒而使代码混乱!
我只是将Eclipse配置为在缺少serialVersionUID时不生成警告。
感谢@ Steve Jessop对此的回答。这是5行代码...几乎没有麻烦。
我@SuppressWarnings("serial")
在有关课程的上方添加了内容。
我还添加了此方法:
private void writeObject(ObjectOutputStream oos) throws IOException {
throw new IOException("This class is NOT serializable.");
}
希望那是史蒂夫的意思:)
即使您知道该对象将被序列化,也无需生成serialVersionUID,因为java会自动为您生成该对象并自动跟踪更改,因此您的序列化将始终正常进行。仅当您知道自己在做什么时才应生成它(向后序列化兼容性,手动更改跟踪等)。
因此,我想说在大多数情况下,禁止警告是最好和最安全的解决方案。
最好为实现可序列化的每个类生成SVUID 。原因很简单。您永远都不知道何时由您或某个第三方将其序列化。可以配置很多服务,这些服务将序列化servlet。对于存在的每个IDE,都会生成一个插件或仅使用模板并设置svuid = 1L。
让Eclipse生成一个ID。快捷方便。警告不容忽视。如果您遇到了要对对象/ has /进行序列化的问题,这也省去了很多麻烦。
1L
一个硬编码的ID(无论是一个生成的ID,还是一个生成的ID ),那么如果您希望一切正常进行,那么每次兼容性发生更改时,您基本上都会承担更新该ID的负担。它们基本上像库版本,但在类级别。指定一个ID然后再不更改它,比不指定它有害得多。(更不用说抛出一个异常,writeObject
这将成为我所预测的维护噩梦)。
如果遗漏了serialVersionUID,则java将在编译时为该类生成一个(每次编译都会更改)。
反序列化对象时,将反序列化对象的serialVersionUID与jvm中的类进行比较。如果它们不同,则认为它们不兼容,并引发异常。例如,在升级程序并反序列化旧类之后,可能会发生这种情况。
我一直使用1L作为serialversionUID。它没有问题(与生成的默认值相比),并且仍然保留了以后通过增加id来破坏兼容性的选项。
这取决于。
如果使用不同的编译器多次编译源代码,则编译后的代码可能具有不同的serializationId,这些序列号会破坏序列化。然后,您需要在代码中显式地坚持一个常量serializationId。它必须是静态的,最终的,并且必须是每个类的(不可继承)。
但是,如果您始终使用特定的编译器编译代码,并且始终将代码一次性部署到所有VM,则可能需要进行严格的版本检查,并希望确保在任何时候都只运行一个版本的代码。在这种情况下,您应该禁止显示警告。因此,如果虚拟机未成功部署且正在运行旧版本的代码,则您可能会期望序列化过程中发生异常,而不是怪异的反序列化对象。碰巧是我的情况,我们过去有一个非常大的集群,我们需要严格的版本检查以发现任何部署问题。
无论如何,您应该尽可能避免序列化,因为与协议缓冲区或节俭相比,默认序列化非常慢,并且不支持跨语言互操作性。