使用serialVersionUID或抑制警告?

发布于 2024-07-07 09:35:03 字数 134 浏览 12 评论 0原文

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

你会做什么以及为什么?

I want to create a class that, for example, extends HttpServlet? My compiler warns me that my class should have a serialVersionUID. If I know that this object will never be serialized, should I define it or add an annotation to suppress those warnings?

What would you do and why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

如此安好 2024-07-14 09:35:03

我不知道 Java 最佳实践,但我突然想到,如果您声称序列化永远不会发生,您可以添加一个抛出异常的 writeObject 方法。 然后抑制该警告,因为您知道它不可能适用于您。

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

  • 该形式在不同版本的代码之间不兼容。
  • 您已经取消了有关这种情况的警告。

添加 ID 听起来像是一个难题,因为您真正想做的不是序列化。 期望调用者不序列化您的对象意味着您希望他们“知道”他们的 HttpServlet 何时属于您的类。 由于您拥有一个不能序列化的可序列化对象,因此违反了多态性,您至少可以做的是确保粗心的调用者知道它。

I don't know Java best practices, but it occurs to me that if you are claiming that serialization will never happen, you could add a writeObject method which throws. Then suppress the warning, safe in the knowledge that it cannot possibly apply to you.

Otherwise someone might in future serialize your object through the parent class, and end up with a default serialized form where:

  • the form isn't compatible between different versions of your code.
  • you've suppressed the warning that this is the case.

Adding an ID sounds like a bodge, since what you really want to do is not serialize. Expecting callers not to serialize your object means that you expect them to "know" when their HttpServlet is of your class. That breach of polymorphism is on your head for having a Serializable object which must not be serialized, and the least you can do is make sure unwary callers know about it.

满地尘埃落定 2024-07-14 09:35:03

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

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

If you do not plan to serialize instances, add a SuppressWarning.

A generated serial ID can be a bit dangerous. It suggests that you intentionally gave it a serial number and that it is save to serialize and deserialize. It's easy to forget to update the serial number in a newer version of your application where your class is changed. Deserialization will fail if the class fields have been changed. Having a SuppressWarning at least tells the reader of your code that you did not intend to serialize this class.

云柯 2024-07-14 09:35:03

我拒绝被 Eclipse 恐吓而给我的代码添加混乱!

我只是将 Eclipse 配置为不生成有关缺少serialVersionUID 的警告。

I refuse to be terrorized by Eclipse into adding clutter to my code!

I just configure Eclipse to not generate warnings on missing serialVersionUID.

晌融 2024-07-14 09:35:03

感谢@Steve Jessop 对此的回答。 总共只有 5 行代码……一点也不麻烦。

我在相关类的上方添加了 @SuppressWarnings("serial") 。

我还添加了这个方法:

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

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

Thanks @ Steve Jessop for his answer on this. It was 5 lines of code... hardly a hassle.

I added @SuppressWarnings("serial") just above the class in question.

I also added this method:

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

Hopefully that's what Steve meant :)

却一份温柔 2024-07-14 09:35:03

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

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

Even if you know this object will be serialized there is no need to generate serialVersionUID because java will automatically generate it for you and will automatically keep track of changes so your serialization will always work just fine. You should generate it only if you know what you are doing (backward serialization compatibility, manual change tracking etc.)

So I would say suppressing the warning is the best and safest solution in most cases.

野味少女 2024-07-14 09:35:03

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

It is good to generate SVUID to every class implementing serializable. The reason is simple. You never know when it will be serialized by you or by some 3rd party. There can be configured a lot of services which will serialize servlets. For every IDE exists plugin which generates one or just use template and set svuid = 1L.

帅哥哥的热头脑 2024-07-14 09:35:03

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

That warning drives me crazy, because every time you subclass a Swing class, you know you're never going to serialize it, but there is that stupid warning. But yeah, I let Eclipse generate one.

今天小雨转甜 2024-07-14 09:35:03

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

Let Eclipse generate an ID. Quick and easy. Warnings are not to be ignored. Also saves you lots of trouble should you ever come to the point where the object /has/ to be serialized.

甜宝宝 2024-07-14 09:35:03

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

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

我总是使用 1L 作为serialversionUID。 它没有什么坏处(与默认生成的相比),并且仍然保留了稍后通过​​增加 id 来破坏兼容性的选项。

If you leave out a serialVersionUID java will generate one for the class at compile time (it changes with every compilation).

When deserializing objects the serialVersionUID of the deserialized object is compared to that of the class in the jvm. If they are different they are considered incompatible and an Exception is thrown. This can happen for instance after upgrading your program and deserializing old classes.

I always use 1L for serialversionUID. It doesn't hurt (compared to the default generated) and it still leaves the option of breaking compatibility later by incrementing the id.

国际总奸 2024-07-14 09:35:03

这取决于。

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

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

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

It depends.

If you use different compilers to compile your source code multiple times, your compiled code could have different serializationIds that will break the serialization. Then you need to stick to a constant serializationId explicitly in your code. It must be static and final and per class (not inheritable).

However, if you always compile your code with a specific compiler and always deploy your code in one shot to all of your VMs, you probably need strict version checking and want to make sure that anytime there is only one version of you code running, in that case, you should just suppress the warning. So in case a VM is not deployed successfully and is running old version of your code, you probably expect an exception during serialization rather than quirk deserialized objects. This happens to be my case, we used to have a very very large cluster and we need strict version checking to find out any deployment issue.

Anyway, probably you should avoid serialization whenever possible since the default serialization is very slow compared to protocol buffers or thrift and does not support cross-language interoperability.

静若繁花 2024-07-14 09:35:03

如果您知道您的应用程序从不序列化事物,则可以抑制警告:

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

(或通过构建工具传递 JAVAC_ARGS。)这样您将收到除“串行”之外的所有警告。 IDE-s 和构建工具(如 Maven/SBT/Gradle)可以很好地配合。

If you know your applications never serializes things, you can suppress the warning:

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

(Or pass through JAVAC_ARGS via your build tool.) Building this way you will have all warnings except "serial". IDE-s and build tools like Maven/SBT/Gradle work fine with that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文