56

java常用序列化解析

 6 years ago
source link: https://mp.weixin.qq.com/s/RFi8wR_1i-raU9htCZ5e_Q
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

java常用序列化解析

认识序列化

序列化对于每一个程序员都算是再熟悉不过的名词了,但是对于市面是各种流行的序列化方式又是否真正了解并能找出一个最适合的序列化方式呢!

概念
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

理解
按上述描述的话 简单的理解就是某一天你对象惹你生气了,怎么办!忍,是不可能了,那就把他给序列化一下 1.选个规则 比如编个号 2.拿起指甲刀 按照编号大卸八十八块。但是当你气消了 怎么办? 一堆脂肪可不会说话,反序列化不就行了 真傻,幸好之前有编号 按照编号再组装到一起 完活。 简单吧 有对象的小朋友可以尝试下!

引玉
估计大家也都清楚了什么是序列化和反序列化接下来就给大家浅析下java 常用的几种序列化方式: JDK自带序列化、JSON序列化、Protostuff序列化 的使用以及实现原理。

JDK序列化

创建要序列化的实体

Image

正反序列化实现

Image

此时会发现JDK自带的序列化在使用上很简单直接通过ObjectOutputStream的 writeObject() 方法将person对象写入到了一个byte数组里 而反序列化的时候再通过ObjectInputStream() 的readObject() 转成对象 并且强转成Person 的对象 那么就引申出一个猜想:是不是在序列化时将对象的所有内容信息都进行了存储!

验证猜想之前先给大家看下结果吧!

Image

接着小编一顿源码分析 找到这段代码

Image

结论
JDK自带的序列化方式稳定性很高因为他将所有的内容都涵盖在序列化后的数组对象里但是因此也会导致一个问题 就是占用了过多的空间去存储并不需要的那些东西,这也是我们对JDK序列化避而远之的原因之一。那Json序列化又会有什么优化吗

JSON序列化

Image

Image

结果证明json序列化的结果不到jdk序列化的一半,说到这儿聪明的小伙伴都已经为什么了 是的看下这张图你就知道了

Image

就是因为json格式的数据只保留了key-value 而其他的无关属性都没保存,所以在反序列化的时候需要使用类来做一个反转的依据,这里就不过多的做说明了!

protostuff 序列化

protostuff是基于protobuff的一种序列化方式,相较于protobuf它更简单不需要再手动创建.proto文件等过程! 使用protostuff首先我们需要引入相关的依赖

<dependency>
 <groupId>io.protostuff</groupId>
 <artifactId>protostuff-runtime</artifactId>
 <version>1.5.3</version>
</dependency>
<dependency>
 <groupId>io.protostuff</groupId>
 <artifactId>protostuff-core</artifactId>
 <version>1.5.3</version>
</dependency>
Image

下面我们来分析下protostuff的序列化过程

首先引入一个schema的概念

官方的解释是
schema是:
对象的序列化逻辑
一个对象的反序列化逻辑
对对象所需字段的验证
对象的字段名到字段号的映射
对象的实例化。

个人的理解:基于类本身所提炼出来的正反序列化所需的所有关键信息!用于正反序列化的验证及实例化

Image

在序列化的时候会根据类型的不同调用RuntimeUnsafeFieldFactory类下相应匿名类的writeto()方法进行序列化,序列化的时候首先会 在类ProtostuffOutput下makeTag

Image

我们可以看出这个Tag包含了fieldNumber 和 WIRETYPE_VARINT 前面的fieldNum代表的是成员变量的序号 后面的WIRETYPE代表的是序列化类型由此我们大概可以了解到protostuff的一些玄机 json用的是变量名 而protostuff用的是变量序号以及类型做标识!

1.protostuff序列化和变量的名字无关!

2.从后面增加减少变量不影响反序列化!

3.当序列化的变量属性变化了是不是序列化失败!

这时我们翻出之前DEMO的运行结果

Image

通过结果我们可以看出Dog的实体能正常反序列化出Person的实体而Cat的实体却报出异常,同时Dog增加的变量为null,所以上面的猜想是成立的,同时发现序列化以后的byte数组是最小的也符合预期

最后声明 本文只是从宏观方面对各种序列化进行分析介绍,并未深入到各序列化底层对不同数据类型的值转成byte[]的具体实现 在底层方面protostuff也是有所优化的有了这些了解相信大家一定会更好的评估自己的需求选择适合自己的序列化方式。

Image

部门招聘

高级Java开发工程师

工作职责:

1、负责58同城APP,58同镇等相关后端研发工作;

2、负责基础平台的架构设计,核心代码开发;

3、调研并掌握业内通用技术方案,引入项目迭代,提升研发效率;

职位要求:

1、3年以上Java互联网项目开发经验;

2、Java基础扎实,编码规范,程序具备较高的健壮性,熟悉常用设计模式;

3、对MVC框架、RPC框架、基础服务组件等有深入的研究;

4、掌握Linux环境下的网络编程、多线程编程,数据结构和算法能力良好;

5、对高并发高可用系统设计有深入的实践经验;

6、具有高度的责任心、勇于承担责任,能承受较强的工作压力;

7、积极主动,敢于接受挑战,有较强的团队合作精神;

高级前端研发工程师

工作职责:

1、负责58同城App前端产品研发;

2、负责58同城前端无线产品某一技术方向,人才培养;

3、前端研发所需类库、框架、脚手架搭建;

4、交互模式调研及创新(React,ReactNative);

职位要求:

1、计算机及相关专业本科以上学历;

2、3年以上前端开发经验,负责过复杂应用的前端设计和开发 ;

3、精通web前端技术(js/css/html),熟悉主流框架类库的设计实现、w3c标准,熟悉ES6/7优先;

4、熟悉前端模块化开发方式(commonjs/webpack …);

5、熟悉移动端开发、自适应布局和开发调试工具,熟悉hybrid app开发;

6、掌握一门后端语言(node/java/php...),对前后端合作模式有深入理解;

7、有良好的产品意识和团队合作意识,能够和产品、UI交互部门协作完成产品面向用户端的呈现;

8、有技术理想,致力于用技术去推动和改变前端研发;

9、熟悉Vue/React/ReactNative优先,有BAT等公司经验优先;

高级Android开发工程师

岗位描述:

1、负责58同城App的研发工作;

2、肩负平台化任务(插件框架,Walle,Hybrid,WubaRN) ;

3、维护和开发服务库,公共库的工作;

4、调研Android前端技术;

5、提升开发效率和应用性能;

职位要求:

1、2年以上的Android开发工作经验;

2、精通Java语言,精通Android Studio开发,了解Gradle编译;

3、精通常用算法、数据结构和架构设计;

4、了解Android性能限制及优化方案;

5、了解常用的开源工具:Volley,RxJava,Fresco等等;

6、了解git, maven等等工具;

7、有插件开发经验,Hybrid开发经验,ReactNative开发经验优先;

8、积极主动、喜欢挑战,有强烈的创业精神,能承受高强度的工作压力;

以上如有小伙伴感兴趣,请发送简历到:

[email protected]


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK