什么是序列化?
序列化就是把对象的信息转换成可存储,可传输的状态,序列化后的对象可以存储在临时或持久化持久性储存区或者在网络中传输
有序列化也有反序列化,反序列化就是从存储区读取序列化后对象,重新创建该对象.
Serializable 与 Parcelable 的区别?
先说一下Seralizable 吧
Serializabe是Java提供的可序列化的接口,当我们点进这个接口一看就会发现这个接口里面啥也没有,嗯,这是一个空接口
Serializable使用起来很简单就是让序列化的类实现这个接口就可以默认帮我们实现序列化了;这时候就有疑问了, 实现一个空接口咋就序列化了?实现Serializable就是给对象一个标识,有了这个标识的对象就默认给序列化了,我们要做的就是根据自己的需求传输或者存储这个对象. 这里我们可以通过I/O流的方式读取或者存储序列化的对象
到这里就不得不说serialVersionUID;serialVersionUID不是必须的,可以指定也可以不指定;如果没有为类指定serialVersionUID,则JVM会自动根据类的内容生成一个serialVersionUID,类中的任何变化均会导致serialVersionUID的变化,如新增一个空格。
因此,若一个类没有指定serialVersionUID,而且发生了变化,则读取磁盘中的对象时就会报错。
指定serialVersionUID的话 序列化数据中的serialVersionUID 与当前类中的serialVersionUID相同才可以被反序列化,也就是说我们指定sserialVersionUID之后很大程度上避免了反序列化失败,指定了SerialVersionUID之后,如果我们的类发生了改变比如增加了一些成员变量或者删除了一些成员变量,只要SerialVersionUID一致,我们仍然可以反序列化成功,这样就可以最大程度的恢复数据
Parcelable
Parcelable也是用来实现序列化的,也是一个接口,但Parcelable不是空接口了,Parcelable是android特有的,下面来看一下Parcelable里面都有哪些东西
打开Parcelable接口可以看到里面:
public interface Parcelable
{
//内容描述接口,基本不用管
public intdescribeContents();
//写入接口函数,打包
public voidwriteToParcel(Parcel dest, int flags);
//读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入
//为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例
publicinterface Creator
{
publicT createFromParcel(Parcel source);
publicT[] newArray(int size);
}
}
Parcelable的实现
实现Parcelable 步骤
1) implements Parcelable
2) 重写 writeToParcel 方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的parcel中,打包需要传递的数据到Parcel容器保存,以便从Parcel容器中获取数据
3) 重写describeContents()方法,内容接口描述,默认返回0就可以
4) 实例化内部静态对象CREATOR实现接口Parcelable.Creator
| publicstaticfinal Parcelable.Creator
这要注意,其中public staticfinal一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。需重写本接口中的两个方法:
createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,newArray( int size)
创建一个类型为T,长度为size的数组,仅一句话即可(returnnewT[size]),供外部类反序列化本类数组使用。
简而言之:通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,
通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,因此写的顺序和读的顺序必须一致。
实现代码如下:
public class MyParcelable implements Parcelable
{
privateint mData;
publicint describeContents()
{
return 0;
}
publicvoid writeToParcel(Parcel out, int flags)
{
out.writeInt(mData);
}
publicstatic final Parcelable.Creator
{
public MyParcelable createFromParcel(Parcel in)
{
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size)
{
return new MyParcelable[size];
}
};
privateMyParcelable(Parcel in)
{
mData = in.readInt();
}
}
选择序列化方法的原则
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好 的保证数据的持续性在外界有变化的情 况下。尽管Serializable效率低点,但此时还是建议使用Serializable。