[关闭]
@JeromeLiee 2020-02-04T00:11:23.000000Z 字数 1249 阅读 493

Java序列化


1. 什么是序列化?

序列化是将Java对象的状态按照一定规则有序地写入字节流中,反序列化就是反过来,按照一定规则从有序地从字节流读出,然后重新创建对象的过程。

因为是关于对象的状态信息保存,所以在序列化的过程,是不会对静态变量和标记了transient关键字的变量进行序列化的。

2. 为什么要序列化?

两个目的:

  1. 数据的持久化存储。因为对象的生命周期不可能超过JVM的生命周期,那么想要在JVM退出后保存对象状态,就需要进行序列化操作;
  2. 跨进程或网络的传输。不同的进程或网络,都存在多个JVM,而对象的存在是依赖于JVM的,所以需要序列化。

3. 序列化的原理

需要被序列化的对象实现Serializable接口,然后调用ObjectOutputStream的writeObject()方法,该方法会调用writeObject0()方法,在writeObject0()方法里,会过滤掉静态变量和标记了transient变量,接下来会检查要被序列化对象的类型,只有String、数组、枚举以及实现了Serializable接口的JavaBean才能被序列化,否则会抛出异常。检查通过后,会将对象的状态信息写入字节流中,以文件的形式存储或通过网络进行发送等。

反序列化则是将上述过程反过来,从文件中或网络中读取字节流,得到其中的对象信息,然后通过类加载器创建对象。

4. serialVersionUID字段

Serializable是个空接口,在编译后会生成一个静态long类型的serialVersionUID字段,在序列化的时候会一同写入字节流中,然后在反序列化的时候会进行该字段的校验,如果一致则创建对象,否则抛出异常。

由于编译生成的serialVersionUID会跟随类的信息变化而变化,所以我们在进行序列化操作时最好手动指定一个变量值,可以防止类信息发生变化时反序列化异常。

5. 引申——Android序列化

Android中的序列化是实现Parcelable接口,IDE会帮我们重写一系列的方法,其中序列化的过程是通过调用Parcel的一系列write方法,将JavaBean的成员变量按照顺序写入到一个Parcel对象中,这个Parcel对象可以在Binder中传输。反序列化就是将通过调用一系列的read方法,从Parcel对象中按照顺序读取字段,然后创建对象。

Serializable使用简单,但其序列化和反序列化都需要进行I/O操作,开销比较大,而Parcelable实现序列化主要用于内存中,开销小,方便跨进程Binder中传输,缺点是实现起来比较麻烦,另外想要进行持久化存储或网络传输也比较麻烦。

所以如果是想要进行持久化存储数据或用于网络传输,那么使用Serializable,如果只是想用于Binder跨进程传输,那么优先使用Parcelable。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注