Serializable,Parcelable和data class的区别

在 Android 开发中,data classSerializableParcelable 是三种常见的对象处理方式,它们有各自的用途和特点。以下是它们的区别:

1. data class

data class 是 Kotlin 提供的一种特殊的类,用于简化数据模型类的声明。

特点:

  • 用于表示数据模型,自动生成常见的方法(toString()equals()hashCode()copy() 等)。
  • 不提供默认的序列化或反序列化功能,需要与其他机制(如 ParcelableSerializable)结合使用。

优点:简洁,减少样板代码。易于比较和拷贝数据对象。

缺点:仅是一个基础结构,不支持直接跨进程传输或持久化。

2. Serializable

Serializable 是 Java 提供的一种序列化接口,用于将对象转换为字节流,以便存储或跨进程传输。

特点:

  • 实现序列化很简单,只需让类实现 Serializable 接口。
  • Java 自带,无需额外依赖。
  • 使用反射机制进行序列化和反序列化。
  • 易于实现,代码简单。
  • 支持 Java 的所有对象。

性能较差:使用反射机制,效率低,序列化的内存开销大。生成的字节流较大,不适合 Android 中的高性能场景。

3. Parcelable

Parcelable是 Android 提供的一种高效的序列化方式,专为在 Android 中使用而设计,常用于在组件间传递对象(如通过 Intent)。

特点:

  • 通过手动实现 Parcelable 接口来控制序列化和反序列化。
  • 基于写入和读取方法,无反射,效率高。

优点:

  • 性能高:更适合 Android 中的高频序列化场景。
  • 更灵活,可自定义序列化逻辑。

缺点:

  • 实现较复杂:需要手动实现 writeToParcel()CREATOR

例子:

4.性能对比

特性data classSerializableParcelable
实现难度简单简单较复杂(但可用 @Parcelize 简化)
性能不涉及序列化差(反射机制,开销大)高(无反射,开销小)
使用场景数据模型持久化或跨进程传输(非高频)Android 中的高频数据传输
序列化效率较低
对象大小较大较小
跨平台无限制跨平台支持Android 特定

5.选择建议

  1. 只用于数据模型:选择 data class,代码更简洁。
  2. 需要跨进程传输但性能要求不高:选择 Serializable,实现简单。
  3. 需要高效的序列化和数据传输:选择 Parcelable,特别适用于 Android 中的 IntentBundle

6. 什么是序列化(Serialization)?

序列化是将对象的状态(属性数据)转换为字节流或其他可存储或传输的格式的过程。

主要作用:

  • 存储:将对象保存到文件或数据库中。
  • 传输:在网络中传输对象,比如在客户端与服务器之间传递数据。
  • 缓存:将对象转化为可恢复的格式,便于后续恢复使用。
data class User(val id: Int, val name: String)

 序列化后

Byte stream: [0x00, 0x01, 0x02, ...]

7. 什么是反序列化(Deserialization)?

反序列化是将序列化后的字节流(或存储格式)重新转换回原始对象的过程。

主要作用:

  • 从存储或传输的格式中重建对象。
  • 恢复数据到应用中,便于程序继续使用。

8.序列化与反序列化的用途

  1. 网络传输:客户端与服务器通过网络传输对象时,数据必须是字节流。序列化将对象转为字节流发送,接收端通过反序列化恢复对象。
  2. 持久化存储:将对象存储到文件、数据库等位置,便于稍后加载。
  3. 跨进程通信(IPC):Android 的 Binder 机制通过序列化对象实现不同组件间的数据传递。
  4. 缓存数据:将对象保存到内存或磁盘中,通过反序列化快速恢复。

在 Android 中:

  • Parcelable:Android 提供的高效序列化接口,专为高性能和内存敏感场景设计
@Parcelize
data class User(val id: Int, val name: String) : Parcelable

在 Java 中:

  • Serializable 接口:对象通过实现此接口进行序列化。

其他方式:通过Gson,Moshi等三方库实现

示例代码

Serializable 示例

// 序列化
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.ser"));
User user = new User(1, "Alice");
out.writeObject(user);

// 反序列化
ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.ser"));
User user = (User) in.readObject();
System.out.println(user.getName());

Parcelable 示例

@Parcelize
data class User(val id: Int, val name: String) : Parcelable

// Intent 传递对象
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", user) // 序列化
startActivity(intent)

// 在目标 Activity 中获取对象
val user = intent.getParcelableExtra<User>("user") // 反序列化

疑问:

data class不具有序列化的性质,那为何在使用网络请求时,并没有对其进行特殊处理?

答:因为Retrofit 这样的网络框架,这些框架自动处理了 data class 的序列化和反序列化。这并不是因为 data class 自身具有序列化的性质,而是因为 网络库(如 Gson 或 Moshi)为其提供了支持

  • 发送请求时:Retrofit 会将你的 data class 对象序列化为 JSON。
  • 接收响应时:Retrofit 会通过 JSON 库将服务器返回的 JSON 反序列化为你的 data class 对象。

 tips:

在创建实体类时,@Keep 注解是非常明智的,这能防止代码混淆(ProGuard/R8)时移除或重命名你的数据类字段,确保使用Gson时可以正确地进行序列化和反序列化。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&岁月不待人&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值