序列化相关概念

序列化的作用及其两种序列化方式的区别

序列化作用

序列化(Serialization) 是将 对象的状态(字段值)转换为可存储或传输的字节序列 的过程;反序列化(Deserialization) 则是将字节序列恢复为对象的过程。其核心作用包括:

  1. 数据持久化存储
    • 将对象状态保存到 文件、数据库或缓存 中,以便程序重启后恢复数据。
    • 例如:用户配置信息、游戏进度、临时缓存数据等。
  2. 跨进程 / 跨网络通信
    • 在分布式系统中,对象需通过网络传输(如 HTTP、RPC 协议),或在 Android 中通过 IntentBinder 跨进程传递数据。
    • 此时需将对象序列化为字节流,经网络传输后再反序列化为目标对象。
  3. 数据格式转换
    • 将复杂对象转换为 JSON、XML 等通用格式,便于与其他系统或服务交互(如 API 接口返回数据)。
  4. 状态传递与恢复
    • 在 Android 中,Activity 被销毁重建时,通过 onSaveInstanceState 序列化临时状态(如文本框内容),重建后反序列化恢复。
    • 在 Java Web 中,HttpSession 存储的对象需实现序列化,以便在服务器集群间复制或持久化。

应用场景详解

  1. 本地数据存储
  • 场景:

    • 保存用户设置(如主题模式、音量偏好)到文件(如 Android 的 SharedPreferences 本质通过 XML 序列化)。
    • 缓存网络请求结果到本地(如图片、JSON 数据),减少重复请求。
  • 技术实现:

    • Java:通过 ObjectOutputStream 将对象写入文件(需实现 Serializable)。

    • Android:使用 ParcelableSerializable 配合 SharedPreferencesRoom 数据库。

    • 示例代码(Java 序列化到文件):

      FileOutputStream fileOut = new FileOutputStream("user.dat");
      ObjectOutputStream out = new ObjectOutputStream(fileOut);
      out.writeObject(user); // 序列化对象
      out.close();
      
  1. 网络传输与跨进程通信
  • 场景:

    • 分布式系统:微服务间通过 RPC(如 gRPC、Dubbo)传递对象,需将对象序列化为二进制格式(如 Protobuf、JSON)。
    • Android 跨进程通信(IPC):通过 Binder 机制传递自定义对象(需实现 Parcelable)。
    • 前端与后端交互:后端将 Java 对象序列化为 JSON 返回给前端(如 Spring MVC 自动将对象转为 JSON)。
  • 关键技术:

    • 序列化协议:JSON(可读性强)、Protobuf(高效二进制)、XML(已逐渐被替代)。

    • Android 示例:

      Intent intent = new Intent(this, TargetActivity.class);
      intent.putExtra("user", user); // user 需实现 Parcelable
      startActivity(intent);
      
  1. 框架与中间件的数据传递
  • 场景:

    • Android 的 ViewModel 组件通过 onSaveInstanceState 序列化数据,防止屏幕旋转时数据丢失。
    • 消息队列(如 Kafka、RabbitMQ)传递对象时,需将消息序列化(如使用 Avro、JSON 格式)。
  • 典型案例:

    class MainViewModel : ViewModel() {
        private val _user = MutableLiveData<User>()
        val user: LiveData<User> get() = _user
    }
    

    若User未序列化,屏幕旋转时ViewModel可能无法正确恢复数据。

Parcelable与Serializable 的性能比较

首先Parcelable 的性能要强于Serializable 的原因

1)在内存的使用中,前者在性能方面要强于后者;

2)后者在序列化操作的时候会产生大量的临时变量,(原因是使用了反射机制) 从而导致GC的频繁调用,因此在性能上会稍微逊色;

3Parcelable是以binder作为信息载体的,在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable,既然是内存方面比价有优势,那么自然就要优先选择;

4)在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是 通过使用IO流的形式将数据读写入在硬盘上;

但是:虽然Parcelable 的性能要强于Serializable,但是仍然有特殊的情况需要使用 Serializable,而不去使用Parcelable,因为Parcelable无法将数据进行持久化,因此 在将数据保存在磁盘的时候,仍然需要使用后者,因为前者无法很好的将数据进行 持久化,(原因是在不同的Android版本当中,Parcelable可能会不同,因此数据的持 久化方面仍然是使用Serializable

总结:Java应用程序中有Serializable来实现序列化操作,Android中有Parcelable来 实现序列化操作,相关的性能也作出了比较,因此在Android中除了对数据持久化的时候需要使用到Serializable来实现序列化操作,其他的时候我们仍然需要使用Parcelable来实现序列化操作,因为在Android中效率并不是最重要的,而是内存。

binder的Parcel默认用哪种序列化

  1. 性能优先
    Parcelable 是 Android 专为跨进程通信(IPC)设计的序列化接口,通过手动实现 writeToParcelcreateFromParcel 方法,避免了反射开销,效率远高于 Serializable(后者基于 Java 反射,性能较差)。
    在 Binder 通信中,数据需频繁跨进程传输,Parcelable高性能特性成为默认选择。
  2. Parcel 底层支持
    Parcel 提供了专用方法读写 Parcelable 对象:
    • writeParcelable(Parcelable value, int flags)
    • readParcelable(ClassLoader loader)
      而对于 Serializable,需通过通用方法 writeSerializable(Object value)readSerializable() 处理,并非默认首选。
  3. Binder 强制要求
    当通过 Binder 传递自定义对象时,必须实现 Parcelable(否则会抛出 AndroidRuntimeException),这进一步确立了 Parcelable 在 Binder 通信中的默认地位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值