不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨— blog.csdn.net/cjm24848365…
(PS:感觉面试的时候如果真的可以把这些点说出来,会显得比较高级,而且还可以使我们的面试时间显得很长,哈哈哈哈哈~)
面试官:“你能说一下Java 与 Android 的序列化原理吗?”
是的,我们之前复习了一遍 《Serializable 和 Parcelable 的区别》 ,但是 Serializable接口 和 Parcelable接口并不等于序列化,如果要再让我们讲一下序列化的原理,我们就要再多知道一点。
首先我们要明白一个概念:什么是序列化?
序列化与反序列化都是一个过程,它并不是一个接口!
序列化就是说当我需要保存信息到内存中或者文件里的时候,我要对这些信息做一些标记和标准规范。
反序列化就是 将来要用到这些信息的时候 可以按照你保存时的逻辑 恢复成你保存之前的样子。
再拿个现实生活中例子,来形象的类比一下。
大家都有搬家的经历,在搬家的时候,比如你有一个很大的可拆卸的柜子,这个时候为了方便,我们会把柜子拆卸之后装箱,在拆卸装箱的时候我会做一些标记,或者制定一些标准,因为我要保证我拆过之后,还能把它拼回原样。---那这种做标记或者按照标准装箱的过程,我们就可以把它理解为序列化。
到了新家之后,我们拆开箱子,按照之前做的标记(或者定下的标准)我们能够很容易的把柜子恢复成原来的样子。---那这种遵循一定的规则能够恢复原样的过程,我们就可以把它理解为反序列化。
所以,这个时候我们明白了 Serializable 和 Parcelable 只是实现序列化的手段之一二而已。
下面,我再来深入的看看它们到底是怎么实现序列化的,原理又是什么?
先说Serializable吧,下面是它的源代码:
恩,你可以看到Serializable接口是空的!
既然是空的,它是怎么做到序列化的呢?
其实啊,这个接口本身并没有做什么,它在这里只是充当了标记的作用。
有没有发现,在源码的注释里有ObjectOutputStream、ObjectIntputStream、ObjectOutput、ObjectInput。
这就是说,只要你的类打上了“Serializable”这个标记,就可以使用outputStream这个流把它写出去,如果没有打上这个标记你就去用流写的话,它就会抛出一个异常。
那打上这个标记之后,它是如何做到序列化与反序列化的呢?
这后续的操作就是由JDK自己完成的了。
比如说我现在有一个Student类 要通过io流把它写到文件中去,这个时候我就必须让它实现Serializable接口。
使用之后,当你用流去写的时候,jdk自己就会把这个类中的所有属性(类型/值/名字等所有信息)打包写到一个文件中去。
这样在以后别人要用它的时候,就能根据标记来恢复,这是一个逆向的过程,所以叫做反序列化。
当然,它底层其实是用的反射,用反射去获取类的属性、名字等等信息。
由于Parcelable是android提供的一个接口。所以它就不再是空的实现了。
还是让我们来看一看源码吧:
因为Parcelable要自己去实现序列化与反序列化,所以它的使用就复杂了很多,在它的注释中也告诉了我们如何去实现Parcelable.
当我们序列化的时候就会去调用writeToParcel()方法,把数据记录到Parcel里去。
它序列化和反序列化的顺序必须相同,不需要借助io。
通看下来,我们可以知道:
Serializable是JDK的规则,具体的序列化 反序列化操作都是有jdk完成的。
Parcelable需要程序员来自己实现序列化与反序列化过程,所以Parcelable使用的时候效率要比Serializable高,但是使用的时候要比Serializable复杂(自己写代码)。
但是我们也发现:他们二者的共同目的是相同的---即把我们的数据按照一定的规则记录下来,如果你需要反序列化的时候 就把数据按照规则给解析恢复出来。
到此我们深深的体会到了 序列化与反序列化都是一个过程,并不是一个接口 这句话了。
并且我们也体会并理解了Serializable、Parcelable都只是实现序列化与反序列的一种方式、一种规则而已。
那我们不经又想到,我们会经常向网络传输数据,也会从网络上获取数据。而它们并没有实现Serializable/Parcelable,那它们又是怎么做的序列化与反序列化的呢?
这个问题其实也不难,大家想想我们在进行网络数据传输的时候都是用的什么呀?
是不是Gson啊、FastJson啊之类的,那我们不难猜测,它们肯定也去实现了序列化与反序列化,只是它们用的是自己的规则而已,比如json。
json这种序列化的方案,它的有点还是很突出的,那就是方便我们进行网络调试,哪里有问题,数据一看就知道了,可读性杠杠滴。
积累点滴,做好自己~