文章目录
引言
序列化过程: 是指把一个 Java 对象变成二进制内容,实质上就是一个 byte数组。
反序列化过程: 把一个二进制内容(也就是 byte[])变回 Java 对象。
1.对序列化和反序列化的理解
①:之所以需要序列化,核心目的是为了解决网络通信之间的对象传输问题。也就是说,如何把当前 JVM 进程里面的一个对象,跨网络传输到另外一个 JVM进程里面。
②:序列化,就是把内存里面的对象转化为字节流,以便用来实现存储或者传输。
③:反序列化,就是根据从文件或者网络上获取到的对象的字节流,根据字节流里面保存的对象描述信息和状态。重新构建一个新的
对象。
④:其次,序列化的前提是保证通信双方对于对象的可识别性,所以很多时候,我们会把对象先转化为通用的解析格式,比如 json、xml 等。然后再把他们转化为数据流进行网络传输,从而实现跨平台和跨语言的可识别性。
2.序列化的选择
市面上开源的序列化技术非常多,比如 Json、Xml、Protobuf、Kyro、hessian等等。
那在实际应用里面,哪种序列化最合适,我认为有几个关键因素:
- 序列化之后的数据大小,因为数据大小会影响传输性能
- 序列化的性能,序列化耗时较长会影响业务的性能
- 是否支持跨平台和跨语言
- 技术的成熟度,越成熟的方案使用的公司越多,也就越稳定。
3.序列化的方式
实现 Serializable 接口或者 Externalizable 接口
实现Serializable接口 | 实现Externalizable接口 |
---|---|
系统自动存储必要的信息 | 程序员决定存储哪些信息 |
Java内建支持,易于实现,只需要实现该接口即可,无需任何代码 | 必须实现接口内的两个方法 |
性能略差 | 性能略好 |
有些字段不想进行序列化怎么办
对于不想进行序列化的变量,使用transient关键字修饰。
transient关键字
在持久化对象时,对于一些特殊的数据成员(如用户的密码,银行卡号等),我们不想用序列化机制来保存它。为了在一个特定对象的一个成员变量上关闭序列化,可以在这个成员变量前加上关键字transient。
transient关键字的作用
transient关键字的作用是控制变量的序列化,在变量声明前加上该关键字,用来表示一个成员变量不是该对象序列化的一部分,可以阻止该变量被序列化到文件中,在被反序列化后,transient变量的值被设为初始值,如int型的是0,对象型的是null。 transient只能修饰变量,不能修饰类和方法。
注:
static修饰的静态变量天然就是不可序列化的。
transient关键字使用总结
(1)变量被transient修饰后,将不再是对象持久化的一部分,该变量内容在序列化后无法被访问。
(2)transient关键字只能修饰变量,不能修饰方法和类。**本地变量是不能被transient关键字修饰的。**变量如果是用户自定义类变量,则该类需要实现Serializable接口。
(3)一个静态变量不管是否被transient修饰,均不能被序列化(如果反序列化后类中static变量还有值,则值为当前JVM中对应static变量的值)。
- 序列化保存的是对象状态,静态变量保存的是类状态,因此序列化并不保存静态变量。
transient关键字使用场景
(1)类中的字段值可以根据其它字段推导出来,如一个三角形类有三个属性:边长、边长对应的高、面积,面积可以根据前面两个字段推导出来,那么面积不需要序列化。
(2) 一些安全性的信息,一般情况下是不能离开JVM的。
(3)如果类中使用了Logger实例,那么Logger实例也是不需要序列化的