关于java:浅谈序列化与反序列化

4次阅读

共计 2360 个字符,预计需要花费 6 分钟才能阅读完成。

什么是序列化?

序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格局(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在雷同或另一台计算机环境中,能复原原先状态的过程。按照序列化格局从新获取字节的后果时,能够利用它来产生与原始对象雷同语义的正本。对于许多对象,像是应用大量援用的简单对象,这种序列化重建的过程并不容易。面向对象中的对象序列化,并不概括之前原始对象所关系的函数。这种过程也称为对象编组(marshalling)。从一系列字节提取数据结构的反向操作,是反序列化(也称为解编组、deserialization、unmarshalling)。《维基百科》

粗略的说,咱们能够将对象在内存中持有的属性称之为对象的状态,那么序列化的作用就就是保留对象的状态,相似于存档。像上面这样:

咱们将学生对象写入到磁盘、内存、或者网络中,这个学生对象只领有两个属性: age 和 name。而后 JVM 在将该对象从内存或磁盘或网络中加载进去,age 还是 20,name 还是 zs。

为什么要引入序列化?

java 引入序列化次要是为了反对两种个性,一是 Java 的近程办法调用(Remote Method Invocation,RMI),它使存活于其余计算机上的对象应用起来就像是存活于本机上一样。当向近程对象发送音讯时,须要通过对象序列化来传输参数和返回值。

再者,对 Java Beans 来说,对象的序列化也是必须的(在撰写本文时被视为失败的技术),应用一个 Bean 时,个别状况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保留下来,并在程序启动时进行前期复原,这种具体工作就是由对象序列化实现的。—《java 编程思维》第四版

补充介绍内容:

  • Java bean 是个什么概念?

谈谈我对 java bean 的序列化是一种失败的技术的了解:

这兴许再说的是 java 默认的序列化机制,java 默认的序列化机制有以下毛病:

  • 无奈跨语言 只能被 java 语言本身所应用。
  • 码流太大 也就是说序列化进去的文件比拟大,这会比拟占用网络带宽。
  • 性能比拟差 这也是有其余序列化机制呈现的起因(后文会对常见的序列化机制做一个简略的介绍)

再有就是反序列化的时候是递归操作,解释一下,假如咱们有这些类叫 A、B、C、D。B 是 A 的成员变量,C 是 B 的成员变量,D 是 C 的成员变量。咱们反序列化 A 的时候,JVM 会从最上面的一层去反序列化。家喻户晓,递归是和栈挂钩的,而后你援用关系比拟深的话,栈就会承受不住,也就是 stackOverflow。所以你反序列化的时候,援用关系就不要太深。

仿佛在大数据畛域会感触比拟亲密, 参看这个答复:

你什么时候对 Java 感到失望?

为什么序列化须要实现 Serializable 接口?

用 jdk 提供的序列化,对应的类须要实现 Serializable 接口。如果你不必 jdk 提供的序列化,不实现 Serializable 接口也行。
Serializable 接口属于标记接口,外面啥也没有,只是起一个标记作用,相当于一个标签。

刚开始我的想法是这个接口是用来判断哪些是须要序列化的,哪些是不须要序列化的,通过 instanceof 判断,如果实现了 Serializable 就是阐明须要进行序列化的,没实现的就是不要进行序列化的。然而起初我又想,这不是应该由开发者来决定吗?
开发者感觉这个对象须要序列化了,就调用对应的办法将对象序列化,不须要的时候必定不会调用啊。

略微牵强一点的解释是, 序列化接口和 serialVersionUID(后文会介绍这个字段的作用)字段关联在一起,造成一种约定。

你看在调用 writeObject0 办法时,就会校验序列化对象有没有实现 Serializable 接口,如果该类没有实现,就序列化不了。

默认序列化须要留神的点

每个实现了 Serializable 接口的类还有一个与之相关联的版本号,咱们称之为 serialVersionUID,他的作用是验证发送方发送的对象和接管方接管的对象是否是相容的,也就是看 serialVersionUID 是不是相等,如果不相等,那么反序列化就会失败。

一般来说,罕用的 IDE 在类实现 Serializable 接口后,就会给一个正告,要求产生一个 serialVersionUID,因为就算你不给,编译器依据 java 平台标准在运行时也会生成 serialVersionUID,serialVersionUID 的值和属性是有关系的,减少或缩小一个属性都会引起 serialVersionUID 的变动。这也是官网倡议要序列化的类 (默认是应用 jdk 提供的序列化机制),务必给一个版本号,这是为了向前兼容,假如你不给,又减少了或缩小了属性,序列化版本号就产生了变动,你反序列化之前的类,就会失败。
这也是阿里巴巴代码规约强调的:

序列化类新增属性时,勿批改 serialVersionUID 字段,否则会导致反序列化失败

常见的序列化框架简介

  • protostuff

google 出品,跨语言,跨平台,性能弱小。

  • FastJson

阿里出品,性能也比拟弱小,仅能在 java 平台应用,所反对的序列化也就是将 json 转成对象,对象转成 json。
同类型的也有 jackson,Gson,都能将 JSON 转成对象。

  • Hessian

粗略的说 Hessian 是一个轻量级的 RPC 框架,也提供序列化性能。

总结一下

  • 什么是序列化?

将数据结构或对象状态转为可取用格局(txt、JSON)。

  • 为什么须要序列化,或者说引入序列化机制?

宏观上来说,是为了暂存对象的状态,为了传递对象,比如说 RMI。

  • 是不是序列化就肯定须要实现 Serializable 接口?

不肯定,须要看你调用对应序列化机制的协定。

参考资料:

  • 你什么时候对 Java 感到失望?
  • Java bean 是个什么概念?
正文完
 0