Android数据对象序列化原理与应用

序列化与反序列化

序列化是将对象转换为可以存储或传输的格式的过程。在计算机科学中,对象通常是指内存中的数据结构,如数组、列表、字典等。通过序列化,可以将这些对象转换为字节流或文本格式,以便在不同的系统之间进行传输或存储。序列化后的数据可以被传输到远程系统,或者存储在磁盘上,以便在需要时进行读取和恢复。序列化的逆过程称为反序列化,即将序列化后的数据重新转换为原始对象的过程。

反序列化是将序列化后的数据恢复为原始对象的过程。在编程中,我们经常需要将对象序列化为字节流或者其他形式的数据,以便在网络传输或者持久化存储中使用。而反序列化则是将这些序列化后的数据重新转换为原始对象。

在不同的编程语言中,反序列化的实现方式可能会有所不同。一般来说,反序列化的过程包括以下几个步骤:

  1. 读取序列化后的数据:从文件、网络传输等地方读取序列化后的数据。
  2. 解析数据:根据序列化的格式,解析数据并还原为原始的对象结构。
  3. 创建对象:根据解析得到的数据,创建对应的对象实例。
  4. 恢复对象状态:将解析得到的数据赋值给对象的属性,恢复对象的状态。

反序列化的过程可以用以下伪代码表示:

data = 读取序列化后的数据
object = 解析数据(data)

在实际应用中,反序列化的方式和具体实现会根据编程语言和序列化库的不同而有所差异。不同的序列化格式有不同的特点和适用场景,开发者可以根据具体需求选择合适的序列化方式。

Android数据对象序列化的用途

Android数据对象序列化的主要用途是将对象转换为字节流的形式,以便在网络传输、持久化存储或进程间通信中使用。具体的用途包括:

  1. 网络传输:在Android开发中,我们经常需要将对象通过网络传输给其他设备或服务器。通过序列化,我们可以将对象转换为字节流,然后通过网络发送给目标设备或服务器,目标设备或服务器再将字节流反序列化为对象进行处理。

  2. 持久化存储:Android应用程序通常需要将数据保存在本地存储中,以便在应用程序关闭后仍然可以访问。通过序列化,我们可以将对象转换为字节流,并将其保存在本地文件或数据库中。当应用程序再次启动时,我们可以将字节流反序列化为对象,以便恢复之前保存的数据。

  3. 进程间通信:在Android中,不同的组件(如Activity、Service、BroadcastReceiver等)可能运行在不同的进程中。通过序列化,我们可以将对象转换为字节流,并通过进程间通信机制(如Binder)将字节流传递给其他进程,其他进程再将字节流反序列化为对象进行处理。

序列化提供了一种方便的方式来在不同的场景中传输和存储对象数据。它在网络传输、持久化存储和进程间通信等方面都有广泛的应用。

Android实现对象序列化的方式

在Android中,常用的实现对象序列化有以下几种方式:

  1. 实现Serializable接口:在需要序列化的类中实现Serializable接口,该接口没有任何方法,只是作为一个标记接口。然后使用ObjectOutputStream将对象写入输出流,使用ObjectInputStream从输入流中读取对象。示例代码如下:
public class MyClass implements Serializable {// 类的成员变量和方法public static void main(String[] args) {// 序列化对象MyClass obj = new MyClass();try {FileOutputStream fileOut = new FileOutputStream("object.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(obj);out.close();fileOut.close();System.out.println("对象已序列化");} catch (IOException e) {e.printStackTrace();}// 反序列化对象MyClass newObj = null;try {FileInputStream fileIn = new FileInputStream("object.ser");ObjectInputStream in = new ObjectInputStream(fileIn);newObj = (MyClass) in.readObject();in.close();fileIn.close();System.out.println("对象已反序列化");} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}
  1. 实现Parcelable接口:Parcelable接口是Android特有的接口,相比Serializable接口,它更高效。在需要序列化的类中实现Parcelable接口,并实现相关方法。然后使用Parcel对象将对象写入Parcel,使用Parcel对象从Parcel中读取对象。示例代码如下:
public class MyClass implements Parcelable {// 类的成员变量和方法protected MyClass(Parcel in) {// 从Parcel中读取数据并赋值给成员变量}public static final Creator<MyClass> CREATOR = new Creator<MyClass>() {@Overridepublic MyClass createFromParcel(Parcel in) {return new MyClass(in);}@Overridepublic MyClass[] newArray(int size) {return new MyClass[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {// 将成员变量写入Parcel}
}
  1. 使用Gson库:Gson是Google提供的一个用于在Java对象和JSON数据之间进行序列化和反序列化的库。可以使用Gson将对象转换为JSON字符串,然后再将JSON字符串转换为对象。示例代码如下:
public class MyClass {// 类的成员变量和方法public static void main(String[] args) {// 序列化对象MyClass obj = new MyClass();Gson gson = new Gson();String json = gson.toJson(obj);System.out.println("对象已序列化为JSON字符串:" + json);// 反序列化对象MyClass newObj = gson.fromJson(json, MyClass.class);System.out.println("JSON字符串已反序列化为对象");}
}

序列化原理

Serializable是Java中的一个接口,用于实现对象的序列化和反序列化。序列化是指将对象转换为字节流的过程,而反序列化则是将字节流转换为对象的过程。

Serializable接口没有任何方法,它只是一个标记接口,用于告诉Java虚拟机,该类可以被序列化。要实现序列化,只需要让类实现Serializable接口即可。

在序列化过程中,Java虚拟机会将对象的状态转换为字节序列,然后可以将字节序列保存到文件、数据库或通过网络传输。反序列化过程则是将字节序列重新转换为对象的状态。

在序列化过程中,Java虚拟机会对对象的各个字段进行序列化。对于基本类型和引用类型,Java虚拟机会自动进行序列化。对于自定义类型,需要实现Serializable接口,并且保证该类型的所有成员变量也是可序列化的。

在反序列化过程中,Java虚拟机会根据字节序列重新创建对象,并将字节序列中的数据赋值给对象的各个字段。

需要注意的是,序列化和反序列化的过程中,对象的构造函数不会被调用。因此,在反序列化过程中,如果需要进行一些初始化操作,可以使用特殊的方法readObject()来实现。

总结起来,Serializable接口提供了一种简单的方式来实现对象的序列化和反序列化。通过实现Serializable接口,可以将对象转换为字节序列,以便在不同的环境中进行传输和存储。

Parcelable是Android中用于实现对象序列化的接口。它的原理是将对象的数据按照一定的格式进行打包和解包,以便在不同的组件之间传输或存储。

具体实现步骤如下:

  1. 实现Parcelable接口:在需要序列化的类中实现Parcelable接口,并实现其中的方法,包括describeContents()writeToParcel(Parcel dest, int flags)

  2. describeContents()方法:该方法返回一个标志位,用于描述Parcelable对象特殊对象的类型。一般情况下,返回0即可。

  3. writeToParcel(Parcel dest, int flags)方法:该方法将对象的数据写入Parcel对象中。在该方法中,需要将对象的各个字段按照一定的顺序写入Parcel对象中,以便在解包时按照相同的顺序读取。

  4. 实现Parcelable.Creator接口:在需要序列化的类中实现Parcelable.Creator接口,并实现其中的方法,包括createFromParcel(Parcel source)newArray(int size)

  5. createFromParcel(Parcel source)方法:该方法从Parcel对象中读取数据,并创建出Parcelable对象。在该方法中,需要按照写入Parcel对象时的顺序读取数据,并将其赋值给相应的字段。

  6. newArray(int size)方法:该方法返回一个指定大小的Parcelable数组。

通过实现Parcelable接口,可以将对象的数据打包成一个Parcel对象,然后可以通过Intent传递给其他组件,或者通过Bundle存储到本地。在接收端,可以通过读取Parcel对象的数据,重新构建出原始的对象。

总结起来,Parcelable的原理就是将对象的数据按照一定的格式进行打包和解包,以实现对象的序列化和反序列化。这种方式相对于Java中的Serializable接口,更加高效和灵活。

Serializable/Parcelable对比

Serializable和Parcelable都是用于实现对象的序列化和反序列化的接口,但在实现方式和性能方面有所不同。

  1. Serializable:
  • Serializable是Java提供的默认序列化机制,通过实现Serializable接口,可以将对象转换为字节流,以便在网络传输或保存到文件中。
  • Serializable使用反射机制,将对象的状态保存到字节流中,然后再从字节流中恢复对象的状态。这种方式相对简单,但效率较低。
  • Serializable的缺点是序列化和反序列化的过程需要大量的I/O操作,对性能要求较高的场景下可能会影响程序的执行效率。
  1. Parcelable:
  • Parcelable是Android提供的专门用于Android平台的序列化机制,通过实现Parcelable接口,可以将对象转换为字节流,以便在Activity之间传递。
  • Parcelable使用了更加高效的序列化方式,将对象的状态拆分为多个字段,分别写入和读取字节流。这种方式相对复杂,但效率较高。
  • Parcelable的优点是序列化和反序列化的过程更加高效,对性能要求较高的场景下可以提升程序的执行效率。

Serializable适用于简单的序列化场景,而Parcelable适用于对性能要求较高的Android平台。在选择使用Serializable还是Parcelable时,需要根据具体的需求和性能要求进行权衡。


数据来自parcelable-vs-serializable,实验结果对比Parcelable的效率比Serializable快10倍以上。

总结

对比SerializableParcelable
所属APIJava APIAndroid SDK API
特点序列化和反序列化会经过大量的I/O操作,产生大量的临时变量引起GC,且反序列化时需要反射基于内存拷贝实现的封装和解封(marshalled& unmarshalled),序列化基于Native层实现
开销相对高相对低
效率相对低相对高
适用场景简单序列化Android

在使用Serializable进行对象的序列化时,有一些注意点需要注意:

  1. 类的定义:被序列化的类需要实现Serializable接口,这是Java提供的一个标记接口,用于表示该类可以被序列化。如果一个类没有实现Serializable接口,那么在进行序列化时会抛出NotSerializableException异常。

  2. 成员变量的序列化:被序列化的类的所有成员变量都会被序列化,包括私有成员变量。但是,如果某个成员变量不希望被序列化,可以使用transient关键字进行修饰,被修饰的成员变量在序列化过程中会被忽略。

  3. 对象引用的序列化:如果一个类中包含其他对象的引用,那么在序列化时,被引用的对象也会被序列化。但是,如果被引用的对象没有实现Serializable接口,那么在序列化时会抛出NotSerializableException异常。为了解决这个问题,可以将被引用的对象设置为transient,或者让被引用的对象也实现Serializable接口。

  4. 序列化版本号:在进行对象的序列化时,会为每个被序列化的类自动生成一个序列化版本号。这个版本号用于在反序列化时判断序列化的类和反序列化的类是否兼容。如果序列化的类和反序列化的类的版本号不一致,会抛出InvalidClassException异常。为了避免这个问题,可以显式地为类指定一个固定的序列化版本号,可以使用serialVersionUID关键字进行指定。

  5. 序列化的安全性:在进行对象的序列化时,需要注意序列化的安全性。因为序列化的数据可以被反序列化成对象,如果序列化的数据被篡改,可能会导致安全漏洞。为了增强序列化的安全性,可以使用加密算法对序列化的数据进行加密,或者对序列化的类进行签名验证。

在使用Parcelable进行序列化时,有几个注意点需要注意:

  1. 实现Parcelable接口:要使一个类可序列化,需要让该类实现Parcelable接口,并实现其中的方法。这些方法包括writeToParcel()createFromParcel()等。

  2. 内部类的序列化:如果要序列化的类中包含内部类,需要确保内部类也实现了Parcelable接口,并在外部类的writeToParcel()createFromParcel()方法中对内部类进行序列化和反序列化。

  3. 序列化顺序:在writeToParcel()方法中,需要按照成员变量的顺序将数据写入Parcel对象。在createFromParcel()方法中,需要按照写入的顺序读取数据。

  4. 序列化和反序列化的一致性:在序列化和反序列化过程中,需要确保写入和读取的数据类型一致。例如,如果在writeToParcel()方法中写入了一个整数,那么在createFromParcel()方法中读取时也需要使用相同的方法读取整数。

  5. 版本控制:如果在序列化的类中进行了修改,需要注意版本控制。可以通过给类添加一个版本号来实现版本控制,以便在反序列化时能够正确处理不同版本的数据。

使用Parcelable进行序列化时,需要确保实现了Parcelable接口,并注意序列化顺序、内部类的序列化、数据类型的一致性和版本控制等问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/125928.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker中安装rabbitMq并配置启动

目录 1. 拉取镜像并安装&#xff08;此处实例安装的是最新版&#xff09;2.查看docker中已安装的镜像和版本3.启动RabbitMq4.配置管理端5.安装完成 1. 拉取镜像并安装&#xff08;此处实例安装的是最新版&#xff09; docker pull rabbitmq2.查看docker中已安装的镜像和版本 …

uni-app微信小程序打开第三方地图

需求 小程序中有个按钮点击以后会调用手机中第三方地图进行导航。参数 位置信息 经度 与纬度。 实现方法 uni.openLocation({latitude: Number(地址纬度),longitude: Number(地址经度),name: 地址名称,address: 地址详情,success: function (res) {console.log(打开系统位置地…

FPGA与ASIC有什么差异?二者该如何选用?

前言 对于一个数字电路的新手来说&#xff0c;这可能是会经常遇到的一个问题&#xff1a;FPGA和ASIC之间的区别是什么? 接下来本文将尝试讲解 “什么是FPGA&#xff1f;” 和 “什么是ASIC&#xff1f;”&#xff0c;然后讲述一些关于FPGA和ASIC的问题&#xff0c;例如它们之间…

【嵌入式】【GIT】如何迁移老的GIF到新的仓库时使用LFS功能并保持LOG不变

一、正常迁移流程 假设有仓库 ssh://old/buildroot-201902 需要迁移到新的仓库 ssh://old/buildroot-201902时,我们可以使用以下命令来完成: # 下载老的仓库 git clone ssh://old/buildroot-201902 # 向新的仓库上传所有的tags git push ssh://new/buildroot-201902 --tag…

Centos7下生成https自签名证书

1、安装openssl yum install openssl2、生成带密码的私有秘钥文件 openssl genrsa -des3 -out server.key 2048使用带密码的私有秘钥文件时需要输入密码&#xff0c;这里直接输入&#xff1a;123456 3、生成不带密码的私有秘钥文件 openssl rsa -in server.key -out serve…

vscode debug skills

1) VSCode 调试 C/C 代码时&#xff0c;如何显示动态分配的指针数组。 创建一个动态分配的一维数组: int n 10; int *array (int *)malloc(n*sizeof(int)); memset(array, 1, n*sizeof(int)); 如果直接 Debug 时查看 array 指针&#xff0c;并不能看到数组所有的值。 查看…

约会杭州云栖2023:为了无法计算的价值一起努力

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

阿里云CTO周靖人:打造一朵AI时代最开放的云

10月31日&#xff0c;在2023云栖大会上&#xff0c;阿里云CTO周靖人表示&#xff0c;面向智能时代&#xff0c;阿里云将通过从底层算力到AI平台再到模型服务的全栈技术创新&#xff0c;升级云计算体系&#xff0c;打造一朵AI时代最开放的云。在现场&#xff0c;周靖人公布了云计…

1. PPT高效初始化设置

1. PPT高效初始化设置 软件安装&#xff1a;Office 2019 主题和颜色 颜色可以在白天与黑夜切换&#xff0c;护眼 切换成了黑色 撤回次数 撤回次数太少&#xff0c;只有20次怎么办 自动保存 有时忘记保存就突然关闭&#xff0c;很需要一个自动保存功能 图片压缩 图…

信息系统项目管理师教程 第四版【第10章-项目进度管理-思维导图】

信息系统项目管理师教程 第四版【第10章-项目进度管理-思维导图】 课本里章节里所有蓝色字体的思维导图

CentOS、linux安装squid搭建正向代理,window11配置正向代理

1.CentOS安装配置squid 1.1.安装 yum install -y squid1.2.修改配置文件 在配置文件添加以下2行代码 acl localnet src 0.0.0.0/0.0.0.0 # add by lishuoboy http_access allow all # add by lishuoboy1.3.启动squid systemctl restart squid2.win11…

golang的类型断言

前言&#xff1a;原因很简单&#xff0c;写的代码panic了。报错如下。为此专门看下golang的类型断言。 “[PANIC]interface conversion: interface {} is string, not float64”。 1、类型断言(assertion) 所谓“类型断言”即判断一个变量是不是某个类型的实例(简单来讲就是判…

【教程】R语言生物群落(生态)数据统计分析与绘图

查看原文>>>R语言生物群落&#xff08;生态&#xff09;数据统计分析与绘图实践 暨融合《R语言基础》、《tidyverse数据清洗》、《多元统计分析》、《随机森林模型》、《回归及混合效应模型》、《结构方程模型》、《统计结果作图》七合一版本方案 R 语言作的开源、自…

Oracle Exadata X7-2掉电宕机导致集群无法启动处理过程

文章目录 前言一、当前的状态是什么&#xff1f;二、集群启动异常怀疑对象1.排查心跳网络异常ping自己私有IP延迟高ping其它主机私有IP不通 2.是否发生过重启 三、日志信息收集ocssd.trc集群crs日志cell的griddisk状态及报错 四、IB交换机的问题排查处理五、紧急恢复业务在IB完…

算法模板之栈图文详解

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、算法模板、汇编语言 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️模拟栈1.1 &#x1f514;用数组模拟实现栈1.1.1 &#x1f47b;栈…

数据分析和互联网医院小程序:提高医疗决策的准确性和效率

互联网医院小程序已经在医疗领域取得了显著的进展&#xff0c;为患者和医疗从业者提供了更便捷和高效的医疗服务。随着数据分析技术的快速发展&#xff0c;互联网医院小程序能够利用大数据来提高医疗决策的准确性和效率。本文将探讨数据分析在互联网医院小程序中的应用&#xf…

钡铼技术ARM工控机在机器人控制领域的应用

ARM工控机是一种基于ARM架构的工业控制计算机&#xff0c;用于在工业自动化领域中进行数据采集、监控、控制和通信等应用。ARM&#xff08;Advanced RISC Machine&#xff09;架构是一种低功耗、高性能的处理器架构&#xff0c;广泛应用于移动设备、嵌入式系统和物联网等领域。…

Redis的特性和应用场景

目录 Redis的特性 内存存储数据 可编程性 可扩展性 持久化 水平扩展性 高可用性 为什么redis是快的 Redis的应用场景 数据库 缓存和会话存储 消息队列 redis是一个客户端服务器结构的程序 Redis是一个在内存中存储数据的中间件,能够用于作为数据库,数据缓存等,能在…

Centos7环境下cmake3.25的编译与安装

文章目录 0 视频传送门1 卸载当前版本2 下载cmake3.25.0并且解压缩3 使用root用户进入解压缩的目录4 开始执行命令5 创建软连接6 检查版本 0 视频传送门 https://www.bilibili.com/video/BV1Gu4y1J7Ev/?vd_source3353f83539e46042d8cf76efb177a8e4 07-Centos7编译安装cmake3.…

如何利用python连接讯飞的星火大语言模型

星火大模型是科大讯飞推出的一款人工智能语言模型&#xff0c;它采用了华为的昇腾910 AI处理器。这款处理器是一款人工智能处理器&#xff0c;具有强大的计算能力和高效的能耗控制能力。 华为昇腾910 AI处理器采用了创新的Da Vinci架构&#xff0c;这种架构在设计上充分考虑了…