首先我们来了解为什么需要序列化
- 卖个关子,大家玩游戏的时候,相信都知道【存档】的功能吧,每次我们重新进入游戏的时候,直接载入存档就可以了,不用重新在重头开始,这样我们的游戏也不会丢失
- 从面向对象的思维考虑,万事万物皆对象,我们游戏中的角色,怪兽,装备等等都可以看做是对象
- 我们再从计算机思维考虑,创建的对象其实都是保存在内存中的,想必大家都知道内存中存储的数据只是暂时性的,断电之后是会消失的,但是游戏如果你手动存档之后就算你几天之后在开机,再次读取存档就可以了,这就很奇怪了,为什么断电之后我得装备和人物信息还都存在,还可以继续玩,这是为什么呢?
- 其实我们只要稍加思考之后知道,我们手动存档之后是将内存中的数据存储在硬盘上的,硬盘的数据在关机之后,是不会消失的,其实这个过程就是对象的持久化,也就是我们今天理解的
序列化
,从我们的磁盘上读取出来的数据其实就是对象的反序列化
什么是序列化
上面引入游戏的概念是为了让大家了解为什么需要序列化和反序列化,简单的总结一下
序列化
是指将我们对象实例的状态存储到媒体的过程反序列化
是我们从媒体中将我们的对象状态转换成对象的过程
抽象点理解
序列化
是将对象转成字节序列的过程
反序列化
是将我们的字节序列转成对象的过程
序列化的目的
- 序列化的最终目的是为了实现对象可以跨平台存储和进行网络传输,而我们的跨平台存储和网络传输使用的是
IO
,IO
支持的格式就是字节数组(byte[]
) - 现在存在的问题, 我们如何将对象转成成字节数组呢?其实我们单纯的将对象转成字节数组还是不可行的,因为没有规则的字节数组我们是没办法还原成对象原本面目的,所以我们必须在对象转成字节数组的时候制就定一种规则(
序列化
),那我们从IO
流里面读取数据的时候可以再根据这种规则把对象还原回来(反序列化
)
序列化的几种方式
序列化只是定义了拆解对象的具体规则,那这种规则肯定也是多种多样的,比如现在常见的序列化方式有:JDK 原生、JSON、ProtoBuf、Hessian、Kryo等。
1.JDK(原生)
作为一个成熟的语言,JDK自带序列化方法。只要实现了Serializable
接口,通过ObjectOutputStream
类将对象变成byte[]字节数组
JDK
序列化会把对象类的描述信息和所有的属性以及继承的元数据都序列化为字节流,所以会导致生成的字节流相对比较大。
简单总结一下:JDK
原生的序列化方式生成的字节流比较大,也不支持跨语言,因此在实际项目和框架中用的都比较少。
2.ProtoBuf
谷歌推出的,是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于通信协议、数据存储等。序列化后体积小,一般用于对传输性能有较高要求的系统。
3.Hessian
Hessian
是一个轻量级的二进制 web service 协议,主要用于传输二进制数据。
在传输数据前Hessian
支持将对象序列化成二进制流,相对于 JDK 原生序列化,Hessian
序列化之后体积更小,性能更优。
4.Kryo
Kryo
是一个 Java 序列化框架,号称Java
最快的序列化框架。Kryo
在序列化速度上很有优势,底层依赖于字节码生成机制。由于只能限定在 JVM 语言上,所以
Kryo
不支持跨语言使用。
5.JSON
JSON
序列化方式生成的是一串有规则的字符串,在可读性上要优于上面几种方式,但是在体积上就没什么优势了。
另外JSON
是有规则的字符串,不跟任何编程语言绑定,天然上就具备了跨平台。
总结一下:JSON
可读性强,支持跨平台,体积稍微逊色。
JSON
序列化常见的框架有:fastJSON
、Jackson
、Gson
等。