serialVersionUID 作用是什么以及如何生成的?
正常不设置serialVersionUID 的序列化和反序列化
先定义一个实体Student.class
,**需要实现Serializable
接口,但是不需要实现get(),set()方法**
测试类,思路是先把Student对象序列化到Student.txt
文件,然后再讲Student.txt
文件反序列化成对象,输出。
输出结果,序列化文件我们可以看到Student.txt
,反序列化出来,里面的字段都是不变的,说明反序列化成功了。
序列化之后,类文件增加了字段,反序列化会怎么样?
先说结果,会失败!!!
我们在Student.java
中增加了一个属性score
,重新生成了toString()
方法。
然后重新调用deserial()
方法,会报错:
从上面的报错信息中,我们可以看到,类型不匹配,主要是因为serialVersionUID
变化了!!!
🙋♂️🙋♂️ **提问环节:我都没有设置serialVersionUID
,怎么变化的???小小的脑袋很多问号**🤔🤔
正是因为没有设置,所以变化了,因为我们增加了一个字段score
,如果我们不设置serialVersionUID
,系统就会自动生成,自动生成有风险,就是我们的字段类型或者长度改变(新增或者删除的时候),自动生成的serialVersionUID
会发生变化,那么以前序列化出来的对象,反序列化的时候就会失败。
实测:序列化完成之后,如果原类型字段减少,不指定serialVersionUID
的情况下,也是会报不一致的错误。
《阿里巴巴 Java 开发手册》中规定,在兼容性升级中,在修改类的时候,不要修改serialVersionUID的原因。除非是完全不兼容的两个版本。所以,serialVersionUID其实是验证版本一致性的。
指定`serialVersionUID`,减少或者增加字段会发生什么?
我们生成一个serialVersionUID
,方法:https://blog.csdn.net/Aphysia/article/details/80620804。
然后执行序列化,序列化出文件Student.txt
后,增加一个字段score
,执行反序列化。
是可以成功的!!!只是新增的字段是默认值0。
所以今后考虑到迭代的问题的时候,一般可能增加字段或者减少字段,都是需要考虑兼容问题的,所以最好是自己指定serialVersionUID
,而不是由系统自动生成。自动生成的,由于类文件变化,它也会发生变化,就会出现不一致的问题,导致反序列化失败。
实测:如果我减少了字段,只要指定了serialVersionUID
,也不会报错!!!
serialVersionUID生成以及作用?
serialVersionUID
是为了兼容不同版本的,在JDK中,可以利用JDK的bin
目录下的serialver.exe
工具产生这个serialVersionUID
,对于Student.class
,执行命令:serialver Student
。
IDEA生成实际上也是调用这个命令,代码调用可以这样写:
如果不显示的指定,那么不同JVM之间的移植可能也会出错,因为不同的编译器,计算这个值的策略可能不同,计算类没有修改,也会出现不一致的问题。
getSerialVersionUID()
源码如下:
可以看到上面是使用了一个内部类的方式,使用特权计算computeDefaultSUID()
:
从上面这段源码大致来看,其实这个计算`serialVersionUID
,基本是将类名,属性名,属性修饰符,继承的接口,属性类型,名称,方法,静态代码块等等...这些都考虑进去了,都写到一个DataOutputStream
中,然后再做hash运算
,所以说,这个东西得指定啊,不指定的话,稍微一改类的东西,就变了...
而且这个东西指定了,没啥事,不要改!!!除非你确定两个版本就不兼容!!!
没事...可能得提桶跑路了
此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~
技术之路不在一时,山高水长,纵使缓慢,驰而不息。
公众号:秦怀杂货店
版权声明: 本文为 InfoQ 作者【秦怀杂货店】的原创文章。
原文链接:【http://xie.infoq.cn/article/2d45c6d31a932c5dceba0df20】。文章转载请联系作者。
评论