admin 管理员组文章数量: 1086019
2024年4月14日发(作者:eclipse的console不显示结果)
关于Serializable的serialVersionUID
众所周知,当某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 serialVersionUID,用来
标明当前class的版本号:
•
如果在序列化写 时的版本号和序列化读 时的版本号,不一致,将会有异常:
•
dClassException:
•
local class incompatible: stream classdesc serialVersionUID = …, local cla
ss serialVersionUID = …
•
那如果在class中不声明这个属性呢?那结果可以就会变得比较诡异了:
•
在序列化写 的时候,虚拟机A会为它计算出一个serialVersionUID,计算的
方法是依据class的信息,再具体我也不清楚了。
•
在序列化读 的时候,虚拟机B也会为class计算出一个serialVersionUID,
然后做比较。
•
那么如果两个虚拟机是不同类型的虚拟机,那么计算方法可能就不一样了,于
是即使相同的class,serialVersionUID也可能会不同,不同的class的,理论上来说,也
存在serialVersionUID相同的可能性,所以,serialVersionUID尽量由我们自己来指定,
而不要由虚拟机来计算。
•
那如果serialVersionUID一致,而class发生了变化呢?
•
如果虚拟机A中的AClass有一个属性,而虚拟机B中的AClass,没有这个属
性,那么这个属性将被忽略,而不会有异常。
•
如果虚拟机A中的AClass没有的属性,而在虚拟机B中多出来的属性,那么
这个属性将被赋予一个缺省值,而不会有异常。
•
如果虚拟机A中的AClass有一个属性,在虚拟机B中的AClass也有这个属
性,但这个属性的类型变了,比如说int变成了long,抑或其他的变化,将会有异常:
•
dClassException:
•
incompatible types for field …
经过序列化而产生的异常都是 dClassException,不会产生.
ClassCastException,两者还是有比较大的区别的,从名字上就可以看得出来。
版权声明:本文标题:关于Serializable的serialVersionUID 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1713072365a618487.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论