Skip to content

Latest commit

 

History

History
83 lines (32 loc) · 4.3 KB

序列化.md

File metadata and controls

83 lines (32 loc) · 4.3 KB

1.什么是序列化,

Java序列化是指把Java对象转换为字节序列的过程

Java反序列化是指把字节序列恢复为Java对象的过程;

2.为什么需要使用序列化和反序列化

不同进程/程序间进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等,而这些数据都会以二进制序列的形式在网络上传送。

当两个Java进程进行通信时,对于进程间的对象传送需要使用Java序列化与反序列化了。发送方需要把这个Java对象转换为字节序列,接收方则需要将字节序列中恢复出Java对象。

3. 序列化的有哪些好处

实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(如:存储在文件里),实现永久保存对象。

利用序列化实现远程通信,即:能够在网络上传输对象。

4. Serializable 和 Parcelable 的区别

Serializable原理(https://juejin.im/post/6844904049997774856)

Serializable接口没有方法和属性,只是一个识别类可被序列化的标志。

Serializable是通过I/O读写存储在磁盘上的, 通过反射解析出对象描述、属性的描述 以HandleTable来缓存解析信息,之后解析成二进制,存储、传输。

Parcel原理(https://www.wanandroid.com/wenda/show/9002)

Parcel翻译过来是打包的意思,其实就是包装了我们需要传输的数据,然后在Binder中传输,也就是用于跨进程传输数据 ,将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象,

它的各种writeXXX方法,在native层都是会调用Parcel.cpp的write方法

Serializable 和 Parcelable 的区别

存储媒介的不同(https://www.jianshu.com/p/1b362e374354)

  Serializable 使用 I/O 读写存储在硬盘上,而 Parcelable 是直接 在内存中读写。很明显,内存的读写速度通常大于 IO 读写,所以在 Android 中传递数据优先选择 Parcelable。

效率不同

Serializable 会使用反射,序列化和反序列化过程需要大量 I/O 操作,

Parcelable 自已实现封送和解封(marshalled &unmarshalled)操作不需要用反射,数据也存放在 Native 内存中,效率要快很多。

5.什么是serialVersionUID

https://cloud.tencent.com/developer/article/1524781

序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道,Java对象是保存在JVM的堆内存中的,也就是说,如果JVM堆不存在了,那么对象也就跟着消失了。

而序列化提供了一种方案,可以让你在即使JVM停机的情况下也能把对象保存下来的方案。就像我们平时用的U盘一样。把Java对象序列化成可存储或传输的形式(如二进制流),比如保存在文件中。这样,当再次需要这个对象的时候,从文件中读取出二进制流,再从二进制流中反序列化出对象。

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致,这个所谓的序列化ID,就是我们在代码中定义的serialVersionUID。

6.为什么还要显示指定serialVersionUID的值?

如果不显示指定serialVersionUID, JVM在序列化时会根据属性自动生成一个serialVersionUID, 然后与属性一起序列化, 再进行持久化或网络传输. 在反序列化时, JVM会再根据属性自动生成一个新版serialVersionUID, 然后将这个新版serialVersionUID与序列化时生成的旧版serialVersionUID进行比较, 如果相同则反序列化成功, 否则报错.

如果显示指定了serialVersionUID, JVM在序列化和反序列化时仍然都会生成一个serialVersionUID, 但值为我们显示指定的值, 这样在反序列化时新旧版本的serialVersionUID就一致了.

在实际开发中, 不显示指定serialVersionUID的情况会导致什么问题? 如果我们的类写完后不再修改, 那当然不会有问题, 但这在实际开发中是不可能的, 我们的类会不断迭代, 一旦类被修改了, 那旧对象反序列化就会报错. 所以在实际开发中, 我们都会显示指定一个serialVersionUID, 值是多少无所谓, 只要不变就行.