序列化基础
一、序列化概念
序列化:将对象转变为字节序列的过程
反序列化:将字节序列恢复为对象的过程
持久化:将对象信息存在磁盘上
广义序列化:xml、json、proto都算得上广义上序列化的数据协议
二、序列化实现方式--Serializable接口
Serializable 用来标识当前类可以被 ObjectOutputStream 序列化,以及被 ObjectInputStream 反序列
化。
1.Serializable的默认实现
Serializable 是一个空接口,所以如果不做任何其他操作,则对象会被以默认方式进行序列化。
public class Person implements Serializable {
private static final long serialVersionUID =10000L;
public String name;
//被transient 修饰的变量将不参与序列化和反序列化,表示为临时变量
public transient int age;
}
2.实现Externalizable的方式自定义序列化
Externalizable接口继承了Serializable, Externalizable定义了俩个抽象方法。
public class Person2 implements Externalizable {
public String name;
public int age;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
//自定义序列化过程
out.writeObject(name);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//此处反序列化的顺序需要和序列化保持一致
name = (String) in.readObject();
}
}
3.Serializable序列化需要注意的点
1.如果类的成员变量是其他对象,则相应的对象也需要实现序列化,如果该对象没有实现序列化,那么会反射调用其空参构造,如果没有空参构造,则会报错。
2.实现序列化的类的子类,可以被序列化,子类不用显示申明。
3.实现Serializable的类,也可以通过定义readObject(ObjectInputStream inputStream)和writeObject(ObjectOutputStream outputStream)两个方法自定义序列化和反序列化过程。这样就不会走默认序列化的逻辑
private void readObject(ObjectInputStream inputStream) throws IOException {
//...
}
private void writeObject(ObjectOutputStream outputStream) throws IOException {
//...
}
4.序列化会导致单例模式失败,因为序列化会通过反射构建对象;
5.静态变量不会被序列化,因为静态变量是类的属性,不是对象的属性;
6.被transient修饰的变量也不会被序列化,transient修饰的变量表示为临时变量。
7.定义serialVersionUID有俩个好处,一个是不同版本的类想兼容,可以定义相同serialVersionUID;
如果不同版本的类不想做兼容,那么就修改serialVersionUID,定义不同的serialVersionUID就可达到目的。
三、序列化实现方式--Parcelable接口
Parcelable是android系统的序列化方式。
Parcelable号称比Serializable的序列化速度快上10倍,主要原因是Parcelable的数据是内存存储,Serializable的数据是磁盘存储。
1.Parcelable实现举例
public class Person3 implements Parcelable {
public String name;
public int age;
protected Person3(Parcel in) {
name = in.readString16NoHelper();
age = in.readInt();
}
/**
* 描述对象类型
*/
@Override
public int describeContents() {
return 0;
}
/**
* 自定义序列化过程,重写方法,一般会自动生成
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString16NoHelper(name);
dest.writeInt(age);
}
/**
* 自定义反序列化过程,定义Creator类,一般会提示,自动生成
* @param dest
* @param flags
*/
public static final Creator<Person3> CREATOR = new Creator<Person3>() {
@Override
public Person3 createFromParcel(Parcel in) {
return new Person3(in);
}
@Override
public Person3[] newArray(int size) {
return new Person3[size];
}
};
}
2.Parcelable实现原理
Parcelable实现的序列化一般用于跨进程通信。
进程A将对象序列化之后,存于共享内存,通知进程B将共享内存的数据进行反序列化。
3.Parcelable与Serializable的比较
1.Parcelable的序列化过程用共享内存实现,也就是实际上数据还在内存,而Serializable需要将数据存于磁盘;
2.Parcelable的反序列化是直接将共享内存解析,而Serializable的反序列化需要从磁盘读取并且使用反射机制构建对象;
3.由于实现方式完全不一样,Parcelable的速度比Serializable更快,也更加节省内存。
4.Parcelable用于android跨进程的通信场景,Serializable用于数据持久化到磁盘的场景。
4.Android为什么用Bundle
1.Bundle内部采用ArrayMap结构存储数据,ArrayMap采用二分法排序,在数据量少的时候性能高
2.Bundle采用Parcelable序列化数据