serialversionuid的作用serialVersionUID 有什么作用该如何使用




serialversionuid的作用serialVersionUID 有什么作用该如何使用

2022-07-21 2:25:04 网络知识 官方管理员



问题

当一个对象实现Serializable接口时,多数ide会提示声明一个静态常量serialVersionUID(版本标识),那serialVersionUID到底有什么作用呢?应该如何使用serialVersionUID?

回答

serialVersionUID是实现Serializable接口而来的,而Serializable则是应用于Java对象序列化/反序列化。对象的序列化主要有两种用途:

  • 把对象序列化成字节码,保存到指定介质上(如磁盘等)
  • 用于网络传输

现在反过来说就是,serialVersionUID会影响到上述所提到的两种行为。那到底会造成什么影响呢?

java.io.Serializabledoc文档,给出了一个相对详细解释:

serialVersionUID是Java为每个序列化类产生的版本标识,可用来保证在反序列时,发送方发送的和接受方接收的是可兼容的对象。如果接收方接收的类的serialVersionUID与发送方发送的serialVersionUID不一致,进行反序列时会抛出InvalidClassException。序列化的类可显式声明serialVersionUID的值,如下:```ANY-ACCESS-MODIFIERstaticfinallongserialVersionUID=1L;```当显式定义serialVersionUID的值时,Java根据类的多个方面(具体可参考Java序列化规范)动态生成一个默认的serialVersionUID。尽管这样,还是建议你在每一个序列化的类中显式指定serialVersionUID的值,因为不同的jdk编译很可能会生成不同的serialVersionUID默认值,进而导致在反序列化时抛出InvalidClassExceptions异常。所以,为了保证在不同的jdk编译实现中,其serialVersionUID的值也一致,可序列化的类必须显式指定serialVersionUID的值。另外,serialVersionUID的修饰符最好是private,因为serialVersionUID不能被继承,所以建议使用private修饰serialVersionUID。

举例说明如下:现在尝试通过将一个类Person序列化到磁盘和反序列化来说明serialVersionUID的作用:Person类如下:

serialversionuid的作用(serialVersionUID有什么作用该如何使用)(1)

简单的测试一下:

serialversionuid的作用(serialVersionUID有什么作用该如何使用)(2)

测试发现没有什么问题。有一天,因发展需要,需要在Person中增加了一个字段email,如下:

serialversionuid的作用(serialVersionUID有什么作用该如何使用)(3)

这时我们假设和之前序列化到磁盘的Person类是兼容的,便不修改版本标识serialVersionUID。再次测试如下

serialversionuid的作用(serialVersionUID有什么作用该如何使用)(4)

将以前序列化到磁盘的旧Person反序列化到新Person类时,没有任何问题。

可当我们增加email字段后,不作向后兼容。即放弃原来序列化到磁盘的Person类,这时我们可以将版本标识提高,如下:

privatestaticfinallongserialVersionUID=2L;

再次进行反序列化,则会报错,如下:

java.io.InvalidClassException:Personlocalclassincompatible:streamclassdescserialVersionUID=1,localclassserialVersionUID=2

谈到这里,我们大概可以清楚,serialVersionUID就是控制版本是否兼容的,若我们认为修改的Person是向后兼容的,则不修改serialVersionUID;反之,则提高serialVersionUID的值。再回到一开始的问题,为什么ide会提示声明serialVersionUID的值呢?

因为若不显式定义serialVersionUID的值,Java会根据类细节自动生成serialVersionUID的值,如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,也有可能会导致不同的serialVersionUID。所以ide才会提示声明serialVersionUID的值。

发表评论:

最近发表
网站分类
标签列表