序列化基础

2021-03-10  本文已影响0人  饭勺

一、序列化概念

序列化:将对象转变为字节序列的过程
反序列化:将字节序列恢复为对象的过程
持久化:将对象信息存在磁盘上
广义序列化: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序列化数据

上一篇下一篇

猜你喜欢

热点阅读