java序列化和反序列化
一:概念
- 序列化:将对象转化为二进制数据(字节序列)的过程成为序列化;
- 反序列化:将二进制数据(字节序列)恢复为对象的过程称为反序列化;
- transient:修饰需要序列化的对象的某些属性,使得被修饰的属性不会被序列化和反序列化;
- serialVersionUID:需要序列化的对象的成员属性,表示该对象的序列化版本id,反序列化的接收对象的serialVersionUID必须保持和序列化对象的serialVersionUID一致,这样才能正常反序列化;但是这点我的实践验证中好像没得到验证,经过大量询问和查阅资料,好像说这点已经被废弃了,即序列化和反序列化已经不关心该值。如果有答案的读者可以帮我答疑解惑下哈
二:应用场景
- 将对象保存到文件中,即存到电脑硬盘中,这时就要使用到序列化;
- mybatis查询缓存启用二级缓存的时候,所映射的pojo对象需要实现序列化,为了将缓存数据取出来进行反序列化;因为mybatis二级缓存的介质多种多样,不一定存在内存中;
- 通过网络传输对象的时候,就一定要用到序列化,将对象转成二进制的字节序列才能在网络上传输;而这种应用场景就是典型的分布式框架当中;分布式框架就是两台不同的物理机子之间的接口调用,数据在网络上从服务提供传输到服务消费者者;被笔者这边也是以此为应用场景进行序列化和反序列化的解释;
三:详细案例
本次案例当中,我的应用场景就是基于dubbo+zookeeper为框架的分布式框架(不理解该框架的读者可以自己百度了解下或者略过该框架),该框架就是两个服务(可以理解为两个不同的项目之间的通信,而这两个项目可以在不同的电脑上运行)之间的调用,需要在网络上将数据转为二进制数据在网络上传输,如果没转为二进制的字节数据,则无法实现传输,如下图,是两个不同的服务:
图一:服务提供者
图二:服务消费者
可以看到消费者:framework项目调用提供者项目course-south项目的接口,返回的数据对象如下图:
t 图三:数据对象
该数据对象正确实现了序列化接口Serializable,所以可以正常调用,调用结果如下:
图四:服务端输出
图五:消费端接收数据
说明返回的对象实现了序列化接口,数据传输没问题;如果没实现序列化接口呢?如下图:
图六:异常
可以看到,当我没有实现序列化接口的时候,服务端查询的数据无法通过网络传输到消费者,所以,证明分布式框架正是序列化和反序列化的一个重要应用场景;
java关键字中有一个和序列化及反序列化关系密切,那就是transient
如果我们的返回的dto有些字段不想进行在网络上进行传输,那这时候就需要将该字段加上transient修饰,所以transient的作用就是所修饰的属性不会进行序列化和反序列化,可能细心的读者就可以发现,在图四和图五当中,图四的输出结果当中的id是有值的,而图五的接收结构的id是没值的;这就是因为我们在返回的对象的id属性上使用了transient修饰,所以提供者在序列化的时候忽略了id的序列化,而消费者在进行反序列化的时候,得到的id值为null,返回数据的对象为图三;