为什么需要对对象进行序列化
- 永久的保存对象数据(将对象数据保存到磁盘中)
- 通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的.因此序列化的目的是将对象数据转换成字节流的形式)
- 需要通过Intent Binder传递对象的时候需要对象实现序列化
Android中实现序列化的两种方式
1. 实现Serializable接口
Serializable是Java所提供的一个序列化接口,它是一个空的接口,为对象提供标准的序列化,反序列化操作。使用Serializable接口实现序列化相对简单。但是还有有一些注意事项,比如显示申明UID,为什么我们需要自己手动添加一个UID呢?
因为如果我们序列化的一个对象的类的属性,或者包名等信息发生了改编的话,那么这个对象的可能在反序列化的爆一个InvalidClassException异常。这是为什么呢?原因就是序列化和反序列化所对应的类的版本发生了改变。JVM不能把数据转换成实例对象。那么问题来了,JVM是怎么来判断类的版本呢?
JVM是通过serialVersionUID来判断类的版本。
如果我们不主动声明serialVersionUID,那么编译器在编译的时候隐式的帮我生成。是通过包名,类名,继承关系,非私有的方法和属性,以及参数,返回值等诸多因子计算出来的。
JVM在反序列化时,会比较数据流中的serialVersionUID和类中的serialVersionUID是否相同,如果相同,则认为该类没有发生变化。
所以为了出现因为类的属性,或者其他发生改变,导致反序列化的时候发生闪退,那么我们在使用Serializable接口的同时手动制定serialVersionUID的值。
2. 实现Parcelable接口
Parcelable接口是Android中的序列化方法,使用也非常简单,只需要实现该接口,就可以实现对象的序列化。
其实系统已经给我们提供了很多实现Parcelable接口的类,它们是可以直接序列化的,比如Intent,Bundle,Bitmap等,同时List和Map也可以序列化。前提是它们里面的每个元素都是可序列化的。
那么问题来了,为什么实现Serializable接口,实现Parcelable接口都可以实现序列化,并且都可以用于Intent间传递数据,那么我们怎么选取呢?
Parcelable与Serializable的性能比较
- 在内存的使用中,前者在性能方面要强于后者
- 后者在序列化操作的时候会产生大量的临时变量,(原因是使用了反射机制)从而导致GC的频繁调用,因此在性能上会稍微逊色
- Parcelable是以Ibinder作为信息载体的.在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable,既然是内存方面比价有优势,那么自然就要优先选择
- 在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上
如何选择哪种序列化方式
Serializable是Java中的序列化接口,其使用起来简单,但是开销很大,序列化和反序列化过程需要大量的I/0操作。而Parcelable是Android中的序列化方式,因为更适合在Android平台上,它的缺点就是使用起来稍微麻烦点,但是它的效率很高,这是Android推荐的序列化方式,因为我们在Android开发中首选Parcelable,Parcelable主要是在内存序列化上,通过Parcelable将对象序列化到存储设备中或者将对象序列化后通过网络传输也都可以的,但是这个过程会稍显复杂,因此在这两种情况下建议使用Serializable。以上就是Parcelable和Serializable的区别。