这几天在学习android知识的进程中,发现在IPC(跨进程通讯)中,运用了Bundle,而Bundle的机制是运用Parcel来进行序列化,而不是运用Serializable。这令我很猎奇。因为究竟java是Android的常用言语,尽管kotlin有后发先至的发展趋势。但是仍是老程序员仍是对java熟悉一些,Serializable作为java的推荐的序列化办法。更应该有着较为完善的优化和策略。所以决议调研学习下,Parcelable的发展历史。

1.什么是Serializable?

Serializable是Java中的一个接口,用于标识一个类的实例能够被序列化,即能够将目标转换为字节省,以便存储到文件、数据库或在网络上传输。Serializable接口是Java序列化的基础,它没有任何办法,仅仅一个符号接口,用于告知Java虚拟机该类的实例能够被序列化。

要使一个类完成Serializable接口,只需求在类的声明中增加implements Serializable即可, 运用Serializable接口的根本步骤如下:

  1. 完成Serializable接口:在类的声明中增加implements Serializable
  2. 创立目标:创立需求序列化的目标。
  3. 序列化目标:运用Java的ObjectOutputStream类将目标序列化为字节省,并写入文件、数据库或网络输出流中。
  4. 反序列化目标:运用Java的ObjectInputStream类从文件、数据库或网络输入流中读取字节省,并将其反序列化为目标。

下面是一个简略的示例,演示了怎样运用Serializable接口进行目标的序列化和反序列化:

import java.io.*;
public class SerializationExample {
    public static void main(String[] args) {
        // 创立目标
        MyClass objectToSerialize = new MyClass("Hello, world!");
        // 序列化目标
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("data.ser");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(objectToSerialize);
            objectOutputStream.close();
            fileOutputStream.close();
            System.out.println("Object serialized successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 反序列化目标
        try {
            FileInputStream fileInputStream = new FileInputStream("data.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            MyClass deserializedObject = (MyClass) objectInputStream.readObject();
            objectInputStream.close();
            fileInputStream.close();
            System.out.println("Deserialized object: "   deserializedObject.getMessage());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class MyClass implements Serializable {
    private String message;
    public MyClass(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
}

2.为什么要序列化

Android为什么不运用Serializable,而是另辟蹊径Parcelable?

为什么要序列化,做个类别,中文写的书本和英文写的书本是怎样存储在电脑中的呢? 很明显中文和英语都最终会转化为二进制编码存储于电脑中,那么二进制是一种通用的转化规范。能够类比我们运用java和python写的不同的应用程序,当想要运行在不同的渠道上面时,就需求将java和python都转化为一种规范,来进行传输。我们能够理解为字节省,而序列化,便是将不同的编程言语的数据转化为一致的字节省的办法。

序列化是将目标的状况转换为可存储传输的格局的进程。在软件开发中,序列化具有以下几个重要的作用:

  1. 耐久化数据:经过序列化,能够将目标的状况保存到磁盘或许数据库中,以便在需求时进行读取和康复。这样能够完成数据的耐久化,即便程序封闭或许重启,数据依然能够保持。
  2. 网络传输:在网络通讯中,需求将目标从一个当地传输到另一个当地。经过序列化,能够将目标转换为字节省,在网络上传输,接收方再将字节省反序列化为目标,从而完成数据的传输。
  3. 跨渠道通讯:不同渠道或许不同言语之间的通讯需求将数据进行序列化和反序列化。经过采用通用的序列化格局,能够完成不同渠道之间的数据交换和通讯。
  4. 分布式体系:在分布式体系中,各个节点之间需求进行数据交换和通讯。经过序列化,能够将目标转换为字节省,在分布式体系中传输,从而完成各个节点之间的数据交换和同享。

总归,序列化是完成数据耐久化、网络传输、跨渠道通讯和分布式体系的重要手法,它供给了一种将目标状况转换为字节省的办法,使得数据能够在不同环境和体系中进行存储、传输和同享,序列化便是将不同言语不同渠道的目标转化为通用的一种流,来传输和存储。

3.Serializable和Parcelable的差异

两者最大的差异在于

1.存储媒介的不同Serializable运用I/O 读写存储在硬盘上,而Parcelable是直接在内存中读写。依据我们日常运用电脑的情况就能够知道,读取内存比读取硬盘的速度要快多了,内存的读写速度通常大于 IO 读写,所以在 Android 中传递数据优先挑选Parcelable

  1. Serializable会运用反射,序列化和反序列化进程需求大量 I/O 操作,Parcelable自已完成封送和解封(marshalled &unmarshalled)操作不需求用反射,数据也存放在 Native 内存中,功率要快很多。

4.为什么Parcelable会比Serializable快10倍

C 供给了四种类型转换:const_cast、static_cast、dynamic_cast、reinterpret_cast。其间reinterpret_cast功能很强壮。能够将目标类型指针转换为long类型的数。而且能够再次经过将该数值转换回目标指针,并能够拜访目标。

// 在堆区别配目标
KPlayer * kPlayer = new KPlayer();
// 将目标指针转换为long类型数值
long playerValue = reinterpret_cast<long>(kPlayer); 
// (在另一个位置) 将刚才的数值,转换回目标指针(要求次目标没有被手动释放过)
KPlayer * kPlayer = reinterpret_cast<KPlayer *>(playerValue );
// 调用目标的办法
kellyPlayer->show();

由此,同享内存的思路,即在Native层新建目标,并将指向目标的指针转换成数值返回Java层。Java层不同进程拿到的是相同的long类型数值,则能够拜访Native层一起的目标。进而完成同享内存。

Parcel序列化的原理,既是将java数据写入同享内存的目标,在另一个位置(或进程),读取数据并反序列化成目标。

5.应该怎样挑选运用Serializable和Parcelable吗

1.当内存中运用时运用Parcelable

2.当耐久化存储时运用Serializable