美文网首页
序列化基础

序列化基础

作者: 饭勺 | 来源:发表于2021-03-10 14:33 被阅读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序列化数据

    相关文章

      网友评论

          本文标题:序列化基础

          本文链接:https://www.haomeiwen.com/subject/fkxwqltx.html