java的Serializable序列化
学习Android第一次进行网络上的数据上传时,就接触到了java的Serializable接口,就有了疑问,为什么要做数据的序列化以及如何进行序列化。
一、什么是序列化
概括的说:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。 序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。 核心作用是对象状态的保存与重建。
反序列化就是需要这个对象的时候,再通过字节流来重建这个对象。
二、如何使用序列化
java序列化的使用方法也相对简单,分为三步
- 实现Serializable接口
- 创建一个ObjectOutputStream流
- 调用writeObject输出可序列化的对象
对应的反序列化也分为两步
- 创建一个ObjectInputStream输入流
- 调用readObject得到相应的反序列化对象
判断一个对象能否序列化,可以看它是否实现了Serializable接口,String的源码中就能看见这样的代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmPci9d5-1601351560887)(/Users/hexuehui/Desktop/屏幕快照 2020-09-29 上午11.25.43.png)]
在序列化对象的时候,如果希望之序列化部分的属性,那就可以使用transient关键字,因为一旦被transient修饰后,这个变量将不再是对象持久化的一部分。
三、谨慎的使用Serializable接口
《Effective Java》这本书中就提到,要谨慎的使用序列化。因为实现示例对象序列化的过程非常的简单,只需要实现Serializable接口就可以了,但是背后缺付出了很大的成本,主要分为三类:
- 降低了代码使用的灵活性,一旦这个类被广泛的使用后,就得永久的支持序列化得到形式,书中也提到了要尽量考虑自定义的序列化形式。
- 第二个就是增大了错误发生的可能性,由于反序列化机制中没有显式的构造器,反序列化要确保:由真正的构造器建立的约束关系,并且不允许攻击者访问正在构造过程中的对象的内部信息。依靠默认的反序列化机制,很容易使对象的约束关系遭到破坏,以及遭受到非法访问。
- 它增加了测试的成本,发布新版本的时候都要考虑到是否对旧的版本兼容,新的实例化是否库在旧版本中反序列化。
所以不要认为使用很简单就是很简单的事情,在使用Serializable实现序列化的时候一定要谨慎。