了解有关serialVersionUID字段的FindBugs警告

时间:2012-08-09 10:43:06

标签: java serialization

我有以下类签名,ClientEventSourc实现Serializable

public class Grid extends ClientEventSource implements Focusable, FramingBlockWrapper,LIMSEditableField

现在FindBugs将此列为狡猾:

Class是Serializable,但未定义serialVersionUID

  

此类实现Serializable接口,但未定义   serialVersionUID字段。更改就像添加引用一样简单   一个.class对象会将合成字段添加到类中   不幸的是,更改了隐含的serialVersionUID(例如,添加了一个   对String.class的引用将生成一个静态字段   类$ java的$ LANG $字符串)。此外,不同的源代码到字节码   编译器可以对合成变量使用不同的命名约定   生成用于引用类对象或内部类。确保   Serializable跨版本的互操作性,考虑添加一个   显式serialVersionUID。

有些人可以解释一下这意味着什么,以及解决这个问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:7)

serialVersionUID用于反序列化您的类。 它默认是自动生成的 但更改类中的任何内容都会生成不同的serialVersionUID,并且您无法反序列化“旧”对象。
所以你定义自己的serialVersionUID来帮助反序列化找到合适的类。

在您的代码中添加如下变量:

private static final long serialVersionUID = 6106269076155338045L;

有关生成UID的参考:

  

Does it matter what I choose for serialVersionUID when extending Serializable classes in Java?

答案 1 :(得分:2)

  

可以解释一下这意味着什么

对该类进行微小更改会更改您不想要的serialVersionUID,因为这可以防止反序列化,没有充分的理由。

  

什么是解决此问题的最佳方法?

按照建议设置它。

private static final long serialVersionUID = 1;
  

是否有任何生成此号码的算法/程序

是。这是您试图绕过的算法,而不是重新创建的算法。从1开始。

  

我的意思是它可以是任何东西,或者它需要遵循某些最佳实践

我建议使用1是最佳做法,因为它清楚地表明这是一个任意选择的覆盖值。使用像6106269076155338045L这样的大值可能看起来像生成的数字或选择了这个数字。

答案 2 :(得分:1)

此值用于反序列化。其目的是保持类及其相应的序列化对象之间的兼容性。如果序列化类型为A的对象,然后以某种方式更改A,则此机制会阻止您反序列化该对象;对象及其类不匹配,您将遇到运行时错误。

JDK中有serialver.exe。如果你给它一个.class文件作为参数,它会吐出serialVersionUID。大多数IDE都内置了此功能。

输入示例:

> serialver MyClass

(已存在文件MyClass.classMyClass必须实施Serializable

输出示例:

> MyClass: static final long serialVersionUID = -8174364448753809256L;

如果你讨厌在命令行做事,那么执行这样的程序:

> serialver -show

将显示此GUI:

serialver screenshot

然后您可以输入班级名称并单击“显示”。

如果您感兴趣,我建议您阅读序列化过程。您可以找到为什么需要此版本ID,生成它时考虑哪些字段/方法等等。