浅谈JAVA序列化与反序列化

序列化介绍

浅谈JAVA序列化与反序列化_第1张图片
对象是由行为和状态组成的,序列化代表我们可以将一个对象的状态转化成数据流,可以通过网络传输,也可以存储成一个文件或者数据库中,同样可以把数据流反序列化成对象。
参见:https://github.com/keyhunter/serialization-test

JAVA序列化

  • Serializable接口:标记一个类能被序列化
  • serialVersionUID字段:序列化版本号
  • transient关键字:标记一个字段是瞬时的,不会被序列化
  • Externalizable接口:序列化扩展接口
  • 继承:当继承时父类如果没有实现Serializable接口
  • 序列化方法:一些用于操作序列化过程的方法
  • 序列化安全:序列化敏感数据的安全性

serialVersionUID

序列化版本号,如果显式声明,则反序列化时,如果类字段变更,仍可反序列化。如果没有该字段,则会默认生成一个(根据类名和字段生成),增加字段后,反序列化时默认生成serialVersionUID改变,则不能反序列化成功。

使用第三方框架序列化则没有此问题

缓存场景,需要特别注意这个

java默认序列化版本号生成:
%JAVA_HOME%/bin/serialver -classpath . com.hello.World

transient修释符

标记一个字段不应该被序列化,可以通过一些特殊手段进行序列化

ArrayList中elementData数组是transient修释的,但通过重写readObject和writeObject,仍然能够被序列化

各种序列化框架都支持该字段

Externalizable接口

Java提供的扩展接口,继承Serializable接口,提供writeExternal和readExternal两个方法

当对象实现了这个接口时,可以灵活的控制它的序列化和反序列过程

第三方序列化框架一般不支持该接口,最好不要使用

继承

当继承时父类如果没有实现Serializable接口

这个情况下,如果只有子类实现序列化接口,父类的状态将不会被序列化

使用第三方框架序列化则没有此问题

序列化方法

java序列化中提供了几个方法处理序列化的过程

readObject(ObjectInputStream ois):如果类中有这个方法,则序列化过程将通过这个方法从输入流读出object

writeObject(ObjectOutputStream oos):如果类中有这个方法,则序列化过程将通过这个方法将objcet写入到输出流

Object writeReplace():如果类中有这个方法,则序列化过程会将这个对象返回并写入到输出流中

Object readResolve():如果类中有这个方法,则最终会返回这个对象到调用的程序中

序列化安全

在需要序列化类的设计中,要考虑之后的兼容性,可以考虑加入版本号

还要考虑安全性,对一些敏感字段的处理上要做加密或者过滤

文本型序列化

优点:文本型序列化的优点在于跨平台跨语言,简单易读易调试,扩展性强
缺点:占空间,不过可以压缩,会有一小部分性能损耗

  • JSON:比较常用,简单,常用的库有Gson,Jackson,FastJson
  • XML: 主要用于基于SOAP协议的应用,序列化后内容太多

二进制序列化

优点:省空间,一般用于系统内部序列化

缺点:扩展性较差,不能够很好的跨语言

  • ProtoBuffer: Google 提供的跨语言跨平台的序列化框架
  • Thirft: 是由Facebook为“大规模跨语言服务开发”而开发的,它被用来定义和创建跨语言的服务,包含一部分二进制的序列化功能
  • hessian: 提供由Servlet访问的hessian
  • kryo: 序列化大对象时性能较好

序列化方式对比

简单对象序列化测试结果:
浅谈JAVA序列化与反序列化_第2张图片
复杂对象序列化测试结果:
浅谈JAVA序列化与反序列化_第3张图片
Kryo:使用Deriect ByteBuffer,对于复杂的对象,序列化快,占用容量小

Proto Buffer:简单对象的序列化比较快

JSON: 一般用于web服务,可读性较强,建议使用fastjson

JAVA: 开箱即用,不需要依赖第三方包

Demo源码地址:https://github.com/keyhunter/serialization-test

一些建议

很多程序员在性能不重要的时候去关注性能。

实际工作中,我们有不同的序列化需求,没有一种最好的万能的序列化方法,只以适合的序列化方法。如果你花时间去优化自己的代码,不好的可以变得更好。如果你只是去改变测试数据,将没有任何意义。

你可能感兴趣的:(JAVA)