序列化是经过某种算法将存储于内存中的对象转换成能够用于持久化存储或者通讯的形式的过程前端
反序列化是将这种被持久化存储或者通讯的数据经过对应解析算法还原成对象的过程,它是序列化的逆向操做算法
前端请求后端接口数据的时候,后端须要返回 JSON 数据,这就是后端将 Java 堆中的对象序列化为了 JSON 数据传给前端,前端能够根据自身需求直接使用或者将其反序列化为 JS 对象后端
RPC 远程调用过程当中,调用者和被调用者必须约定好序列化和反序列化算法,好比 A 应用将 User 对象序列化为了 JSON 数据传给 B 应用,User 对象数据为 {"id": 1, "name": "long"}
,到达 B 应用的时候须要将这些数据反序列化为对象,若是此时 B 应用的反序列化算法是 XML 的话那么确定就解析失败了,因此必须都得约定好他们都采用 JSON 序列化算法,那么基于 JSON 标准就能成功解析出 User 对象数组
若是某个字段咱们不想经过 Java 默认序列化机制输出,咱们就能够经过该字段来代表当前字段不须要被序列化性能
咱们想经过自定义的方式将 address 数据序列化优化
其中的 writeObject 做用于写序列化数据的时候会反射调用该方法,readObject 会在反序列化的时候调用3d
若是咱们没有自定义 serialVersionUID 的话,会根据当前类的信息自动生成,若是当前类没有作修改那么生成的 serialVersionUID 是一致的,若是修改后 serialVersionUID 就会改变致使没法反序列化,因此在平常使用中咱们必定要填写该字段code
最开始看代码的时候,不要一下就陷入所有细节,咱们应该只看咱们目前关注的点,当认识逐渐深入以后再来看一些细节,否则的话容易看的一脸懵逼 cdn
首先调用objectOutputStream.writeObject(user);
而后调用 writeObject0(obj, false);
在这个方法里面有这样一段代码对象
首先将 TC_OBJECT 这一个对象标志位写入到流中,标识着当前开始写一个的数据是一个对象,而后调用 writeSerialData 开始写入具体数据
首先会得到 ClassDataSlot 咱们能够把它看作是提供了序列化对象的辅助手段
在此经过 ClassDataSlot 去检查序列化对象中是否实现了 writeObject 这个方法,那么这个 writeObjectMethod 是在何时初始化的呢?立刻会讲到
若是实现了 writeObject 咱们就去反射调用该方法
若是当前类没有实现 writeObject 方法就调用默认的 defaultWriteFields 去写数据
在上文咱们知道是经过 writeObjectMethod 这个来判断的,那么这个字段是在哪里初始化的呢,咱们回到 ObjectOutputStream 的 writeObject0 方法,在调用后续的 writeOrderinaryObject 方法以前有这样一段代码
而后咱们回到 defaultWriteFields(Object obj, ObjectStreamClass desc) 继续来看
反序列化其实就是序列化的逆向过程,若是你看懂了序列化的关键代码,那么看这个过程就不会很难,下面贴出关键代码作出分析
这里可以看到会根据反序列对象的具体类型分别作不一样的处理,咱们当前的对象是 User 对象因此会进入箭头指向的方法
对于 String 类型来讲,在反序列化第一张中会调用读取对应的值
一个新的技术的诞生都是有必定的缘由和背景的,好比说 Java 原生序列化后数据比较大,传输效率低,同时又又没法跨语言通讯,因此不少人选择使用 XML 的来序列化数据,XML 序列化后却是解决了跨语言通讯的问题,可是它序列化后的数据比原生数据还要大,因此就诞生了 JSON 序列化,他支持跨语言,而且序列化后的数据远远小于前 2 者,最后有人想进一步的优化大小就引入了 Protobuf 它具有 压缩的功能,被压缩的数据小于 JSON 序列化后的数据。
其它的序列化方式
后面会写一篇文章就会来聊聊其它的序列化方式对比下他们的性能和底层使用原理