Java序列化与反序列化

1.什么是Java序列化与反序列化? java

序列化:将java对象转换为字节序列的过程叫作序列化及Serialization(序列化)是一种将对象以一连串的字节描述的过程;redis

反序列化:将字节对象转换为java对象的过程叫作反序列化及是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。spring

序列化:将对象变为--------------------------->文件中数据数据库

反序列化:将文件中的数据------------------------>转换为对象json

2.为何须要Java序列化与反序列化?缓存

(1)、存储网络

在java系统运行过程当中,java对象只存在于堆栈中,可是一旦系统中止运行了,或者某次交互回话结束后,这些java对象也不存在了,架构

想要再次得到java对象,则须要从一些存储设备中读取数据,而且还原为原先的java对象,系统才能够再次正常运行。框架

这里存储设备,能够是文件,缓存(好比EhCache,MemCache,redis等等),甚至是数据库中,均可以,保存这些对象的字节流,等待java对象再次复活!jvm

(2)、传输&交换

分布式系统中,系统之间交互,好比经过java原生的RMI远程调用,返回的字节流反序列化为java对象,才能在jvm里运行。

Java中,一切都是对象,在分布式环境中常常须要将Object从这一端网络或设备传递到另外一端。 这就须要有一种能够在两端传输数据的协议。Java序列化机制能够作到。

或者当下经常使用的分布式架构,http+json返回的json数据,也是须要反序列化为java对象,只是用的方法和jdk原生不一样罢了,

以及新的分布式架构,thrift,dubbo等,返回的数据是字节流的形式,也是须要反序列化。

3.怎么Java序列化与反序列化?

 java JDK自带的序列化工具备

java.io.ObjectOutputStream表明对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把获得的字节序列写到一个目标输出流中。

java.io.ObjectInputStream表明对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类彻底由自身来控制序列化的行为,而仅实现Serializable接口的类能够 采用默认的序列化方式 。

对象序列化通常包括以下步骤:

1) 建立一个对象输出流,它能够包装一个其余类型的目标输出流,如文件输出流;

2) 经过对象输出流的writeObject()方法写对象。

对象反序列化的步骤以下:

1) 建立一个对象输入流,它能够包装一个其余类型的源输入流,如文件输入流;

2) 经过对象输入流的readObject()方法读取对象

特殊说明下:实现Serializable接口的java对象,有一个serialVersionUID,s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D​:​ 字​面​意​思​上​是​序​列​化​的​版​本​号​,凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量,

同一个java对象只要序列化ID相同,属性相同,那么反序列化会正常的执行

同一个java对象,若是序列化ID不一样,属性相同,反序列化都不会成功

由于默认的JDK序列化与反序列化方法要求必须实现Serializable接口,而且序列化ID相同,这时jvm才承认字节流是能够反序列化的,

4.有没有造好的轮子?

java序列化的框架目前也很多,具体实现没来得及一一研究,有基于json反序列化的(GSON,Jackson),有基于字节流实现的(protobuf),以及基于xml等等

5.应用实例:

spring-data-redis 存数据的时候要序列化,取数据的时候要反序列化

当须要把一个对象以hash存储在redis中时候,我是很轻松愉快的写完了。

而后写测试用例,相应的实体bean属性存值竟然为null,debug屡次,发现仍是null值。

因而找到个人bean类,将其 implements Serializable 感受这下应该 test success 了,

可可是,还特么是null。

个人bean类已经实现了序列化接口,安静了片刻,去看bean的父类fatherbean,父类fatherbean 并无implements Serializable,而后果断将父类fatherbean implements Serializable, 再一测,这时真正的 test success 了

那么书上是这么说的。。

当父类继承serializable 接口时,全部的子类均可以被序列化

子类实现了serializable接口,父类没有,父类中的属性不能被序列化(不报错,数据会丢失),可是在子类中属性仍能正确序列化。

若是序列化的属性是对象,则这个对象也必须实现serializable接口,不然会报错

在反序列化时,若是对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错

在反序列化时,若是serialVersionUID被修改,则反序列化时回失败

6.反思下:

1) Serializable Externalizable 接口有何不一样?

2) Serializable 接口有几个方法? 若是没有方法,那么为何会有这样的接口?

3) serialVersionUID 有何用途? 若是没定义会有什么问题?

4) 若是你不但愿某些成员被序列化,应该怎么作?

5) 序列化某个对象时,若是某个成员没有实现 Serializable 会怎样?

6) 若是某个类实现了 Serializable ,但父类没实现,那么当执行反序列化的时候,对象状态是怎样的?

7) 可否自定义序列化的过程?

8) 若是超类实现了 Serializable,那么之类如何避免被序列化?

9) Java 在进行对象序列化和反序列化的时候,用到了哪一个方法?

10) 若是你已经将某个类的实例序列化到磁盘,这时候再往这个类添加新的属性,那么反序列化该对象的时候会发生什么?

11) 什么是 Java 序列化机制中的兼容和不兼容的变化?

12) 可否经过网络来传输序列化对象?

13) 什么类型的变量不会被序列化?

Transient修饰的属性,不会被序列化到文件里,原来初始化的是什么值,最终保持的就是什么值。

相关文章
相关标签/搜索