关于Serializable的rialVersionUID

更新时间:2023-05-07 04:02:52 阅读: 评论:0

  关于SerializablerialVersionUID
众所周知,当某class实现了Serializable接口后,由此class构建出的对象将具备序列化的能力,而Serializable这个接口中没有任何需要实现的方法,所以这个接口的作用仅仅是作为一个标记,告诉虚拟机,具有这个标记的对象,是可以被序列化的,而没有这个标记的则不要序列化。所以,虚拟机应该是可以将任何对象序列化的,只不过是它遵守了一个道德规范,仅序列化那些被允许可以序列化的。那为什么不是所有的对象都是可序列化的呢?我想也许是基于安全性的考量吧。
序列化的一般过程是:
1. 在虚拟机A中,构造了class AClass的对象AObject
2. AObject序列化写入到文件ObjectFile
3. 在虚拟机B中,读取文件ObjectFile
4. 根据AClass和读取进来的byte[],构造虚拟机B中的AClass的对象BObject
这里面,不好理解的事情是在第四步中,如果虚拟机B仅有AObject的数据,并不足以构造出BObject,它必须还需要有AClass的信息。也就是说,序列化,仅仅是把对象以二进制的形式写入到了文件之中,但是这些二进制该组织成什么样的一个东西,却并不能说明,所以还需要AClass的类型信息,这就如同交给了你一大堆的机器零件,还需要你拥有一本组装说明书,你才能把这些零件组装成一架波音747:)。也就是说,序列化的仅仅是Object,而没有同时把这个Object所依赖的所有class一并序列化过去。那为什么不这么做呢?也许和ClassLoader有关?又和安全性有关?
在实现了Serializable接口的class中,需要声明一个long rialVersionUID,用来标明当前class的版本号:
如果在序列化 时的版本号和序列化 时的版本号,不一致,将会有异常:
java.io.InvalidClassException:
local class incompatible: stream classdesc rialVersionUID = …, local class rialVersionUID = …
那如果在class中不声明这个属性呢?那结果可以就会变得比较诡异了:
o 在序列化 的时候,虚拟机A会为它计算出一个rialVersionUID,计算的方法是依据class的信息,再具体我也不清楚了。
o 在序列化 的时候,虚拟机B也会为class计算出一个rialVersionUID,然后做比较。
o 那么如果两个虚拟机是不同类型的虚拟机,那么计算方法可能就不一样了,于是即使相同的classrialVersionUID也可能会不同,不同的class的,理论上来说,也存在rialVersionUID相同的可能性,所以,rialVersionUID尽量由我们自己来指定,而不要由虚拟机来计算。
那如果rialVersionUID一致,而class发生了变化呢?
o 如果虚拟机A中的AClass有一个属性,而虚拟机B中的AClass,没有这个属性,那么这个属性将被忽略,而不会有异常。
o 如果虚拟机A中的AClass没有的属性,而在虚拟机B中多出来的属性,那么这个属性将被赋予一个缺省值,而不会有异常。
o 如果虚拟机A中的AClass有一个属性,在虚拟机B中的AClass也有这个属性,但这个属性的类型变了,比如说int变成了long,抑或其他的变化,将会有异常:
java.io.InvalidClassException:
incompatible types for field …
经过序列化而产生的异常都是 java.io.InvalidClassException,不会产生java.lang.ClassCastException,两者还是有比较大的区别的,从名字上就可以看得出来。

本文发布于:2023-05-07 04:02:52,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/863770.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:序列化   属性   需要   对象   没有   组装
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图