Serializable和Pacelable序列化接口

最近有些面试提到了序列化与反序列化的知识点,答得挺混乱的,找些资料总结一下。

序列化的目的

JAVA 提供一种对象序列化的机制,在该机制中,一个对象可以被表示为一个字节序列,该字节序列中包含对象类型、对象中的数据及其数据类型。通过反序列化,可以根据字节序列内的内容重新在内存中新建这个对象。
主要的应用场景:
1.永久性的保存对象,保存对象的字节序列到本地文件中。
2.通过序列化对象在网络中传递数据。
3.通过序列化对象在进程间传递数据。

Serializable接口

java提供的的一个序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作。使用Serializable来实现序列化相当简单,只需要在类的声明中添加指定serialVersionUID即可。通过Serializable方式实现对象的序列化几乎不用我们自己做任何事情,对象的序列化和反序列化工作都被系统自动完成。

private static final long serialVersionUID = 123456789987654L;

不指定serialVersionUID也可以实现序列化,但是只有序列化后的数据中的serialVersionUID和当前类的serialVersionUID一致时才能正常地被反序列化。serialVersionUID的使用机制是:序列化时会将serrialVersionUID写入序列化文件中,当反序列化时系统会检测文件中的serialVersionUID是否与当前类的serialVersionUID一致,如果一致则说明序列化的类的版本和当前类的版本是相同的,可以成功被反序列化,否则说明类已经发生了变化,无法正常反序列化。

一般来说我们都是手动指定serialVersionUID的值,但是也可以让Eclipse根据当前类的结构自动去生成它的hash值。如果不自己手动指定它的值,一旦反序列化时当前类有所改变,比如增加或者删除某个成员变量,那么系统会重新计算当前类的hash值并把它赋给serialVersionUID,当前类的serialVersionUID和序列化的数据中serialVersionUID不一致,这样反序列化就会失败了。

注意
1.静态成员变量属于类不属于对象,所以不参与序列化过程。
2.被transient修饰的成员变量不参与序列化过程。
3.系统的默认序列化工程可以被改变,直接重写系统默认序列化和反序列化方法即可,writeObject \ readObject

Parcelable接口

Android特有的一个实现序列化的方式。Parcelable也是一个接口,只要实现这个接口,这个类的对象就可以实现序列化并可以通过Intent和Binder传递。

public class A implements Parcelable {
    
    public int a;
    public String b;

    protected A(Parcel in) {
        a = in.readInt();
        b = in.readString();
    }

    public static final Creator<A> CREATOR = new Creator<A>() {
        @Override
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

        @Override
        public A[] newArray(int size) {
            return new A[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(a);
        dest.writeString(b);
    }
}

Parcel对象中包装了可序列化的数据,可以在Binder中自由传输。在序列化过程中需要实现的功能有序列化、反序列化和内容描述。序列化功能由writeToParcel方法完成,通过Parcel中的一系列write方法来实现;反序列化由CREATOR 完成,其内部描述了如何创建序列化的对象和数组,并通过Parcel的read方法来完成反序列化过程;内容描述则由describeContents方法完成,几乎所有情况下这个方法都应该返回0,仅当当前对象中存在文件描述符时,此方法返回1。

使用

Parcelable和Serializable都能实现序列化,且都能在Intent间的数据传递使用。
Serializable是JAVA的序列化接口,其使用起来简单但是开销很大,序列化和反序列化过程需要大量I/O操作,产生大量的临时变量,从而引起频繁的GC,Serializable接口主要用于对象序列化到存储设备中或者将对象序列化后通过网络传输。
Pacelable是Android中的序列化接口,更适用于Android平台,缺点是使用麻烦,优点是效率很高,Pacelable接口在外界有变化的时候不能保证数据的持续性,所以不能用于将数据存储在磁盘上,主要用于内存序列化中。

发布了7 篇原创文章 · 获赞 1 · 访问量 430

猜你喜欢

转载自blog.csdn.net/hust_edu_csdn_123/article/details/100015327
今日推荐