序列号 java_JAVA序列号的serialVersionUID-程序员宅基地

技术标签: 序列号 java  

serialVersionUID 的规范

ff46206c5d0722706dca6ac60dd9ad0e.png

Serializable 和 Externalizable

Java类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。

如果读者看过Serializable的源码,就会发现,他只是一个空的接口,里面什么东西都没有。Serializable接口没有方法或字段,仅用于标识可序列化的语义。但是,如果一个类没有实现这个接口,想要被序列化的话,就会抛出java.io.NotSerializableException异常。

序列号在写成二进制流的时候,会调用如下的方法:

1a5bdcd7a7578cf2f2b99b5c90ad1175.png

Externalizable继承自Serializable,该接口中定义了两个抽象方法:writeExternal()与readExternal()。

当使用Externalizable接口来进行序列化与反序列化的时候需要开发人员重写writeExternal()与readExternal()方法。否则所有变量的值都会变成默认值。

transient 不需要被序列化

transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

什么是 serialVersionUID

序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道,Java对象是保存在JVM的堆内存中的,也就是说,如果JVM堆不存在了,那么对象也就跟着消失了。

而序列化提供了一种方案,可以让你在即使JVM停机的情况下也能把对象保存下来的方案。就像我们平时用的U盘一样。把Java对象序列化成可存储或传输的形式(如二进制流),比如保存在文件中。这样,当再次需要这个对象的时候,从文件中读取出二进制流,再从二进制流中反序列化出对象。

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致,这个所谓的序列化ID,就是我们在代码中定义的serialVersionUID。

这是因为,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

为什么必须设置默认的 serialVersionUID 值

如果我们没有在类中明确的定义一个serialVersionUID的话,看看会发生什么。

尝试修改上面的demo代码,先使用以下类定义一个对象,该类中不定义serialVersionUID,将其写入文件。

3a67bb8cd6fdbc5d9e3463fea8579321.png

然后我们修改User1类,向其中增加一个属性。在尝试将其从文件中读取出来,并进行反序列化。

101382c8ef983f46e43802452c14377e.png

执行结果:

java.io.InvalidClassException: com.hollis.User1; local class incompatible: stream classdesc serialVersionUID = -2986778152837257883, local class serialVersionUID = 7961728318907695402

同样,抛出了InvalidClassException,并且指出两个serialVersionUID不同,分别是-2986778152837257883和7961728318907695402。

从这里可以看出,系统自己添加了一个serialVersionUID。

所以,一旦类实现了Serializable,就建议明确的定义一个serialVersionUID。不然在修改类的时候,就会发生异常。

serialVersionUID有两种显示的生成方式:

一种是默认的1L,比如:

private static final long serialVersionUID = 1L;

另外一种是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:

private static final long serialVersionUID = xxxxL;

后面这种方式,可以借助IDE生成,后面会介绍。

背后原理

为了简化代码量,反序列化的调用链如下:

c11e38ed243c209000d4c493bb17b47c.png

在initNonProxy中 ,关键代码如下:

7236fbe15e0ca4d4d98d3147d13054ef.png

在反序列化过程中,对serialVersionUID做了比较,如果发现不相等,则直接抛出异常。

深入看一下getSerialVersionUID方法:

在没有定义serialVersionUID的时候,会调用computeDefaultSUID 方法,生成一个默认的serialVersionUID。

这也就找到了以上两个问题的根源,其实是代码中做了严格的校验,并且在未定义的时候自动生成了一个serialVersionUID。

IDEA提示

为了确保我们不会忘记定义serialVersionUID,可以调节一下Intellij IDEA的配置,在实现Serializable接口后,如果没定义serialVersionUID的话,IDEA(eclipse一样)会进行提示:

4467bdb1f5068136ac8a2d7cc80d74dc.png

并且可以一键生成一个:

78726b1dd8fde72e8e5305fdd166c9d9.png

当然,这个配置并不是默认生效的,需要手动到IDEA中设置一下:

5d4703d806fb44147e7cd6b1383ef7c0.png

在图中标号3的地方(Serializable class without serialVersionUID的配置),打上勾,保存即可。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42393342/article/details/114160585

智能推荐

广工数字逻辑与EDA设计课程EDA设计实验报告_广工eda实验报告-程序员宅基地

文章浏览阅读759次,点赞7次,收藏6次。基本要求:写上实验目的、实验环境及器件、实验内容和实验结果,附上 Verliog代码、测试平台、综合结果图(RTL 视图及工艺视图) ,综合前仿真、综合后仿真、布局布线后仿真的截图,并写出心得体会。EDA 设计实验报告。_广工eda实验报告

在textarea中插入图片的办法(转载)_textarea插入图片-程序员宅基地

文章浏览阅读2.2w次,点赞3次,收藏17次。原文地址:http://www.cnxinhua.com/html/17688.html 最近一个客户要求这个功能----在textarea中插入图片,用来模仿UBB代码,但又不同于UBB,原因是UBB点击某个图片的时候,在textarea中插入的是一些特殊的字符,而他要求的是将图片插入到textarea中。太难实现了,原因是textarea中只允许插入文字,不允许插入图片,找了很长时间,最终还是_textarea插入图片

头歌-Python入门之运算符的使用_比较和逻辑运算符头歌-程序员宅基地

文章浏览阅读410次。【代码】头歌-Python入门之运算符的使用。_比较和逻辑运算符头歌

【OJ每日一练】1031 - 温度换算_1031: 温度转换-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏4次。文章对你有所帮助的话,欢迎给个赞或者 star,你的支持是对作者最大的鼓励,不足之处可以在评论区多多指正,交流学习。输入一个华氏温度,要求输出摄氏温度。公式为 c=5(F-32)/9 输出要求有文字说明,取位2小数。摄氏温度,浮点数,四舍五入后保留两位小数。一个华氏温度,浮点数。_1031: 温度转换

LINUXE下执行php 定时任务-程序员宅基地

文章浏览阅读39次。linuxtest.php<?php $fn='/home/root.adminssh/boz/logs';$data=rand(1,9999);$fp=fopen($fn,'wb');fwrite($fp,$data);fclose();?>linux下执行命令/usr/bin/php -f ./test.php转载...

shell 变量匹配-程序员宅基地

文章浏览阅读546次。${var%pattern}${var%%pattern}${var#pattern}${var##pattern}${var%pattern},${var%%pattern} 从右边开始匹配${var#pattern},${var##pattern} 从左边开始匹配${var%pattern} ,${var#pattern} 表示最短匹配,匹配到就停止,非贪婪..._shell匹配tag的变量怎么写

随便推点

notepad宏的使用,定制各种操作,比如删除一整行、从当前位置到行末用某字符替换_note pad 删除 宏录制-程序员宅基地

文章浏览阅读1.4k次。删除一整行点击菜单中的【宏】-【开始录制】。鼠标在任意一行内容上单击,使光标停在这行。然后在键盘上找到home键,按下,这时光标不管之前在哪个位置,现在光标都会出现在这行的最前面,这时按住shift键不松,再在键盘上找到end键然后按下。这时就选中这一行了。然后按两次delete键,就把当前行删除了。点击【宏】-【停止录制】。再点击【宏】-【保存录制宏】。然后根据提示,填写名称和选择快捷键的组合,在这我选择的是Ctrl+E。然后点击OK保存。可以看到保存成功了可以直接点击来使用,或者_note pad 删除 宏录制

T168_Debug222\appl\Barcode\Two\DataMatrix文件:IDMXORPK.C-程序员宅基地

文章浏览阅读933次,点赞26次,收藏22次。* None *//* None *//* None *//* None *//* None *//* None */#else#endif#endiffor (;count-- )#endif#else#endif#endiffor (;count-- )#endif。

Springcloud:. yaml.snakeyaml.scanner.ScannerException: while scanning for the next token found char-程序员宅基地

文章浏览阅读587次。Caused by: org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token found character '@' that cannot start any token. (Do not use @ for indentation)_canner.scannerexception: while scanning for the next token found character

C语言带你从实现一个通讯录开始,由“静态版”——>“动态内存版”——>“文件操作版“的万字超级详细分享,从此熟练掌握和运用基本的数组,指针,结构体, 动态内存管理和文件操作!_创建通讯录;在通讯录上实现:查找、增加、删除、修改和打印输出通讯录中所有元素等-程序员宅基地

文章浏览阅读8.1k次,点赞31次,收藏13次。如果你对独立完成一个C语言小程序还毫无头绪,那这篇文章将我将手把手和你一起完成一个通讯录项目,其中包括数组,自定义函数,结构体,指针,动态内存管理和C语言文件操作的结合应用,保姆级教学,超万字的全站最详细教程,简直不要太好,而且每部分知识点可单独任君挑选食用,走过路过,不要错过了呦!_创建通讯录;在通讯录上实现:查找、增加、删除、修改和打印输出通讯录中所有元素等

电磁场第二章公式总结_线电荷密度与电场强度公式-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏20次。1.电荷计算公式根据电荷密度的定义,如果已知某空间区域V中的电荷体密度,则区域V中的总电量q为q=∫Vρ(r⃗)dVq=\int_{V}\rho(\vec{r})dVq=∫V​ρ(r)dV如果已知某空间曲面S上的电荷面密度,则该曲面上的总电量q 为q=∫SρS(r⃗)dSq=\int_{S}\rho_S(\vec{r})dSq=∫S​ρS​(r)dS如果已知某空间曲线上的电荷线密度,则该..._线电荷密度与电场强度公式

鼠标右击没有新建WORD、EXCEL、PPT选项卡解决方案_win11右键新建没有ppt-程序员宅基地

文章浏览阅读1.5k次。鼠标右击没有新建WORD、EXCEL、PPT选项卡解决方案_win11右键新建没有ppt

推荐文章

热门文章

相关标签