serialVersionUID的作用(可序列化)【新手上路】

学习Servlet时,编译器出现了以下一个警告

The serializable class MyServlets does not declare a static final serialVersionUID field of type long


那么究竟什么是serialVersionUID呢?
   看名称:`serial`指的是序列的、串行的;`version`指版本,UID指某种id的话,大致意思就是**序列化的版本ID**
   由此,得明白**序列化与反序列化**的概念

序列化与反序列化

序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

  • 在Java与他语言进行交互(比如与前端js进行http通信),需要把对象转化成一种通用的格式比如json(前端显然不认识Java对象),从对象到json字符串的转换,就是序列化的过程,反过来,从json字符串转换成Java对象,就是反序列化的过程。
  • 在Java需要把一个对象的状态保存到文件或数据库中时,就是数据存取的过程中的中间过程

简单来说,其实就是对象和某种字节流相互转换的过程,这个字节流可供给其它场合使用,不仅仅是JVM中

所以个人理解,由此看来的序列化与反序列化的过程类似于

顶层应用层 与 底层物理层 中间交互的过程


serialVersionUID

而serialVersionUID 的版本号,作用就是与每一个可序列化的类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类

如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException

简单来说,这个版本号会验证序列化 和 反序列化过程中,对象是否还保持一致(或者兼容)

什么情况下不一致:例如在没有显示声明版本号时,先将对象进行了序列化;然后不管是出于什么目的,这个对象的类被修改了,哪怕仅添加了一个强制转换,或是将一个public的属性私有化了,都会影响版本号。此时在这个环境下用反序列化的方法读取以前的对象,是会报错的,就是上述的InvalidClassException

而在有显示声明版本号的情况下,只要前后过程中没有人为修改版本号,JVM都会认为是可以兼容的。除非发生了其他类型的异常


其他:

任何实现了Serializable接口的可序列化类,可以通过声明名为 “serialVersionUID” 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID

private static final long serialVersionUID = 987654321L;

如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java™ 对象序列化规范”中所述。

不过,强烈建议所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。

因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类 – serialVersionUID 字段作为继承成员没有用处。
数组类不能声明一个明确的 serialVersionUID,因此它们总是具有默认的计算值,但是数组类没有匹配 serialVersionUID 值的要求。



  有任何问题欢迎指正,如果这篇文章有帮到您,也请左上角点个赞哦,谢谢!

猜你喜欢

转载自blog.csdn.net/SeasonSoy/article/details/81701414