什么是serialVersionUID,为什么我应该使用它?

serialVersionUID缺失时,Eclipse会发出警告。

可序列化类Foo不声明long类型的静态最终serialVersionUID字段

什么是serialVersionUID ?为什么它很重要? 请显示缺少serialVersionUID会导致问题的示例。


java.io.Serializable的文档可能与您所获得的解释一样好:

序列化运行时与每个可序列化类关联一个称为serialVersionUID的版本号,在反序列化过程中使用该版本号来验证序列化对象的发送者和接收者是否已加载该对象的与序列化相容的类。 如果接收者已经为与对应的发送者类具有不同serialVersionUID的对象加载了类,则反序列化将导致InvalidClassException 。 一个可序列化的类可以通过声明一个名为“ serialVersionUID ”的字段来声明自己的serialVersionUID,该字段必须是static,final和long类型的:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

如果可序列化类没有显式声明serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。 但是,强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类详细信息高度敏感,这可能因编译器实现而异,因此在反序列化期间可能会导致意外的InvalidClassExceptions 。 因此,要确保跨不同的java编译器实现保持一致的serialVersionUID值,可序列化的类必须声明显式的serialVersionUID值。 还强烈建议显式serialVersionUID声明尽可能使用private修饰符,因为这些声明仅适用于立即声明的类 - serialVersionUID字段作为继承成员是无用的。


如果你序列化只是因为你必须序列化为实现的缘故(谁在乎你是否序列化一个HTTPSession,例如...如果它存储与否,你可能不关心反序列化表单对象) ,那么你可以忽略这一点。

如果您实际使用序列化,则只有在计划直接存储和检索使用序列化的对象时才重要。 serialVersionUID表示您的类版本,如果您的类的当前版本不与其以前的版本向后兼容,则应该增加它。

大多数情况下,你可能不会直接使用序列化。 如果是这种情况,请通过单击快速修复选项来生成默认的序列化uid,不用担心。


我无法放弃这个机会来插入Josh Bloch的着作Effective Java(第2版)。 第11章是关于Java序列化的不可或缺的资源。

根据Josh,自动生成的UID是基于类名,实现的接口以及所有公共和受保护成员生成的。 以任何方式更改这些内容都将更改serialVersionUID 。 因此,只有在确定不会有超过一个版本的类将被序列化(跨进程或稍后从存储中检索到)时,您才不需要混淆它们。

如果您现在忽略它们,并且稍后发现需要以某种方式更改该类,但保持与该类的旧版本的兼容性,则可以使用JDK工具serialver在旧类上生成serialVersionUID ,并明确设置那就是新班级。 (根据您的更改,您可能还需要通过添加writeObjectreadObject方法来实现自定义序列化 - 请参阅Serializable javadoc或上述第11章。)

链接地址: http://www.djcxy.com/p/593.html

上一篇: What is a serialVersionUID and why should I use it?

下一篇: How to make a chain of function decorators?