最近有个大众号粉丝和我聊了聊他面试的经历,一个刚入坑Android两年的新人,因为异地的原因视频面试,而面试官只问了一个问题:“JDK自身供给了Serializable序列化接口,为什么还要运用 Parcelable?”,结果他一时语塞面试OVER。说实话听到这个问题,我也有些懵逼,平常忙着研讨各种组件、什么高可用框架,可真要回头对Java根底知识较起真,发现自己的技术债欠的太多,所以和咱们一同复习一下Java序列化知识。

回忆

什么是序列化?

首要咱们要了解什么是序列化?序列化是将目标的状态信息转换为能够存储或传输的形式的进程,序列化最主要的用途便是在传递和保存目标的时分,保证目标的完整性和可传递性。

就相当于咱们现在要把埃菲尔铁塔彻底一摸一样的搬到北京,完成这个进程便是序列化的进程。咱们需要给埃菲尔铁塔的每个部件都打上符号,这个钢筋部件本来在哪个位置,搬到北京后仍然要在对应的位置。这便是将埃菲尔铁塔序列化了之后传输(运输)到北京。而反序列化自然便是利用运到北京的部件依据符号信息复原的进程。

Serializable的原理

那么JDK傍边完成的Serializable序列化接口是如何将一个目标进行序列化的?

static class SerializableTest implements Serializable {
    int i;
    long j;
​
    public SerializableTest(int i, int j) {
      this.i = i;
      this.j = j;
     }
​
    @Override
    public String toString() {
      return "SerializableTest{" +
          "i=" + i +
          ", j=" + j +
          '}';
     }
}
​
​
@Test
public void testSerialible() throws IOException, ClassNotFoundException {
    SerializableTest serializableTest = new SerializableTest(1, 2);
       //序列化
    ObjectOutputStream os = new ObjectOutputStream(
      new FileOutputStream("SerializableTest"));
    os.writeObject(serializableTest);
    os.close();
​
       //反序列化
    ObjectInputStream is = new ObjectInputStream(new FileInputStream("SerializableTest"));
    SerializableTest serializableTest1 = (SerializableTest) is.readObject();
    System.out.println(serializableTest1);
}

关于JVM来说,要进行耐久化的类有必要要有一个符号,只要持有这个符号JVM才答应类创立的目标能够经过其IO体系转换为字节数据,从而完成耐久化,而这个符号便是Serializable接口。而在反序列化的进程中则需要运用serialVersionUID来确认由哪个类来加载这个目标,如果咱们在序列化中没有显现地声明serialVersionUID,则序列化运行时将会依据该类的各个方面计算该类默许的serialVersionUID值。 可是,Java官方强烈建议所有要序列化的类都显现地声明serialVersionUID字段,因为如果高度依赖于JVM默许生成serialVersionUID,或许会导致其与编译器的完成细节耦合,为了保证跨不同Java编译器完成的serialVersionUID值的一致,完成Serializable接口的有必要显现地声明serialVersionUID字段。

总之完成了Serializable接口就相当于给类打上了一个符号,JVM就能够对类目标信息依照(Serializable)规矩记载,而反序列化就依照规矩解析即可。

Parcelable的原理

public class MyParcelable implements Parcelable {
   private int mData;
    public int describeContents() {
     return 0;
    }
   //序列化
   public void writeToParcel(Parcel out, int flags) {
     out.writeInt(mData);
    }
     //反序列化
   public static final Parcelable.Creator<MyParcelable> CREATOR
       = new Parcelable.Creator<MyParcelable>() {
     public MyParcelable createFromParcel(Parcel in) {
       return new MyParcelable(in);
      }
     public MyParcelable[] newArray(int size) {
       return new MyParcelable[size];
      }
    };
   
   private MyParcelable(Parcel in) {
     mData = in.readInt();
    } 

咱们经过Serializable的运用能够发现,Serializable需要运用IO对序列化数据直接写入到文件傍边。而Parcelable是android特有的序列化方法,咱们在开发中或许并不需要将数据保存到文件傍边,只在内存中进行传输运用,此刻运用Parcelable将更为高效,因为Parcelable依赖于Parcel,Parcel的意思是包装,完成原理是在内存中树立一块同享数据块,序列化和反序列化均是操作这一块的数据,而不像Serializable需要运用IO。

JDK本身提供了Serializable序列化接口,为什么还要使用 Parcelable?破案了

对比

  • Serializable是java序列化的方法,存取的进程有频繁的IO,功能较差,可是完成简略。
  • Parcelable是android序列化的方法,采用同享内存的方法完成用户空间和内核空间的交换,功能很好,可是完成方法比较复杂。
  • Serializable能够耐久化存储,Parcelable是存储在内存中的,不能耐久化存储。

今天分享到此结束,对你有帮助的话,点个赞再走呗,好像写的有点浅,咱们凑合看下吧,下期更精彩~

重视大众号:Android老皮
解锁 《Android十大板块文档》 ,让学习更贴近未来实战。已构成PDF版

内容如下

1.Android车载应用开发体系学习指南(附项目实战)
2.Android Framework学习指南,助力成为体系级开发高手
3.2023最新Android中高级面试题汇总+解析,离别零offer
4.企业级Android音视频开发学习路线+项目实战(附源码)
5.Android Jetpack从入门到精通,构建高质量UI界面
6.Flutter技术解析与实战,跨渠道首要之选
7.Kotlin从入门到实战,全方面提高架构根底
8.高级Android插件化与组件化(含实战教程和源码)
9.Android 功能优化实战+360全方面功能调优
10.Android零根底入门到精通,高手进阶之路

敲代码不易,重视一下吧。ღ( ・ᴗ・` )