当缺少serialVersionUID时,Eclipse会发出警告。

可序列化类Foo未声明静态finallong类型的serialVersionUID字段

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


当前回答

如果您序列化只是因为为了实现而必须序列化(例如,谁会关心您是否为HTTPSession序列化……如果它是否存储,您可能不关心对表单对象进行反序列化),那么您可以忽略这一点。

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

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

其他回答

这个问题在Joshua Bloch的《有效Java》中有很好的记录。一本非常好的书,是一本必读的书。我将概述以下原因:

序列化运行时为每个可序列化类提供一个名为Serialversion的数字。此编号称为serialVersionUID。现在这个数字背后有一些数学,它是基于类中定义的字段/方法得出的。对于同一类,每次都会生成相同的版本。在反序列化过程中使用此数字来验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类。如果接收方为对象加载的类具有与对应发送方类不同的serialVersionUID,则反序列化将导致InvalidClassException。

如果类是可序列化的,则还可以通过声明名为“serialVersionUID”的字段来显式声明自己的serialVersionUID,该字段必须是静态的、final的和long类型的。大多数IDE(如Eclipse)都可以帮助您生成长字符串。

如果CheckStyle能够验证实现Serializable的类上的serialVersionUID是否具有良好的值,即它与串行版本id生成器将生成的值相匹配,这将是一件好事。例如,如果您有一个包含大量可序列化DTO的项目,那么记住删除现有的serialVersionUID并重新生成它是一件痛苦的事,而目前验证这一点的唯一方法(据我所知)是为每个类重新生成并与旧类进行比较。这是非常痛苦的。

简单解释:

您正在序列化数据吗?序列化基本上是将类数据写入文件/流等。反序列化是将数据读回类。你打算投入生产吗?如果您只是用不重要的/假的数据测试一些东西,那么不要担心它(除非您是直接测试序列化)。这是第一个版本吗?如果是,请将serialVersionUID设置为1L。这是第二、第三等prod版本吗?现在您需要担心serialVersionUID,并且应该深入研究它。

基本上,如果在更新需要写入/读取的类时没有正确更新版本,那么在尝试读取旧数据时会出现错误。

为什么在Java中的Serializable类中使用SerialVersionUID?

在序列化期间,Java运行时为类创建一个版本号,以便以后可以对其进行反序列化。此版本号在Java中称为SerialVersionUID。

SerialVersionUID用于序列化数据的版本。只有当类的SerialVersionUID与序列化实例匹配时,才能对其进行反序列化。当我们不在类中声明SerialVersionUID时,Java运行时会为我们生成它,但不建议这样做。建议将SerialVersionUID声明为私有静态最终长变量,以避免默认机制。

当您通过实现标记接口java.io.Serializable将类声明为Serializable时,如果您没有使用Externalizable接口自定义进程,java运行时将该类的实例通过默认Serialization机制持久化到磁盘中。

另请参阅为什么在Java中的Serializable类中使用SerialVersionUID

例如,缺少serialVersionUID可能会导致问题:

我正在研究这个JavaEE应用程序,它由一个使用EJB模块的Web模块组成。web模块远程调用EJB模块,并传递实现Serializable的POJO作为参数。

这个POJO的类被打包在EJB jar中,并被打包在WEB模块的WEB-INF/lib中它自己的jar中。它们实际上是同一个类,但当我打包EJB模块时,我打开了这个POJO的jar,将其与EJB模块打包在一起。

对EJB的调用失败,出现以下异常,因为我没有声明其serialVersionUID:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52