当前位置: 首页 > news >正文

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接口,并注意序列化顺序、内部类的序列化、数据类型的一致性和版本控制等问题。

相关文章:

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

序列化与反序列化 序列化是将对象转换为可以存储或传输的格式的过程。在计算机科学中&#xff0c;对象通常是指内存中的数据结构&#xff0c;如数组、列表、字典等。通过序列化&#xff0c;可以将这些对象转换为字节流或文本格式&#xff0c;以便在不同的系统之间进行传输或存…...

Linux cp命令:复制文件和目录

cp 命令&#xff0c;主要用来复制文件和目录&#xff0c;同时借助某些选项&#xff0c;还可以实现复制整个目录&#xff0c;以及比对两文件的新旧而予以升级等功能。 cp 命令的基本格式如下&#xff1a; [rootlocalhost ~]# cp [选项] 源文件 目标文件 选项&#xff1a; -a&…...

SpringBoot 接收不到 post 请求数据与接收 post 请求数据

文章归档&#xff1a;https://www.yuque.com/u27599042/coding_star/xwrknb7qyhqgdt10 SpringBoot 接收不到 post 请求数据 接收 post 请求数据&#xff0c;控制器方法参数需要使用 RequestParam 注解修饰 public BaseResponseResult<Object> getMailCode(RequestParam…...

vue3学习(十四)--- vue3中css新特性

文章目录 样式穿透:deep()scoped的原理 插槽选择器:slotted()全局选择器:global()动态绑定CSScss module 样式穿透:deep() 主要是用于修改很多vue常用的组件库&#xff08;element, vant, AntDesigin&#xff09;&#xff0c;虽然配好了样式但是还是需要更改其他的样式就需要用…...

Python爬虫基础之Requests详解

目录 1. 简介2. 安装3. 发送请求4. 处理响应5. IP代理6. Cookie登录参考文献 原文地址&#xff1a;https://program-park.top/2023/10/27/reptile_4/ 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由…...

C++求根节点到叶子节点数字之和

文章目录 题目链接题目描述解题思路代码复杂度分析 题目链接 LCR 049. 求根节点到叶节点数字之和 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表…...

C++搜索二叉树

本章主要是二叉树的进阶部分&#xff0c;学习搜索二叉树可以更好理解后面的map和set的特性。 1.二叉搜索树概念 二叉搜索树的递归定义为&#xff1a;非空左子树所有元素都小于根节点的值&#xff0c;非空右子树所有元素都大于根节点的值&#xff0c;而左右子树也是二叉搜索树…...

软件工程17-18期末试卷

2.敏捷开发提倡一个迭代80%以上的时间都在编程&#xff0c;几乎没有设计阶段。敏捷方法可以说是一种无计划性和纪律性的方法。错 敏捷开发是一种软件开发方法论&#xff0c;它强调快速响应变化、持续交付有价值的软件、紧密合作和适应性。虽然敏捷方法鼓励迭代开发和灵活性&…...

课题学习(九)----阅读《导向钻井工具姿态动态测量的自适应滤波方法》论文笔记

一、 引言 引言直接从原论文复制&#xff0c;大概看一下论文的关键点&#xff1a; 垂直导向钻井工具在近钻头振动和工具旋转的钻井工作状态下&#xff0c;工具姿态参数的动态测量精度不高。为此&#xff0c;通过理论分析和数值仿真&#xff0c;提出了转速补偿的算法以消除工具旋…...

阿里云服务器—ECS快速入门

这里对标阿里云的课程&#xff0c;一步步学习&#xff0c;链接在下面&#xff0c;学习完考试及格即可获取阿里云开发认证和领取证书&#xff0c;大家可以看看这个&#xff0c;这里我当作笔记&#xff0c;记一下提升印象&#xff01; 内容很长&#xff0c;请耐心看完&#xff0…...

Hive简介及核心概念

本专栏案例数据集链接: https://download.csdn.net/download/shangjg03/88478038 1.简介 Hive 是一个构建在 Hadoop 之上的数据仓库,它可以将结构化的数据文件映射成表,并提供类 SQL 查询功能,用于查询的 SQL 语句会被转化为 MapReduce 作业,然后提交到 Hadoop 上运行。 …...

CrossOver 23.6.0 虚拟机新功能介绍

CrossOver 23.6.0 Mac 此应用程序允许您运行为 Microsoft Windows 编写的程序&#xff0c;而无需实际安装操作系统。 CrossOver 23.6.0 Mac 包括一个 Windows 程序库&#xff0c;用于它可以运行的 Windows 程序。 您会发现非常流行的应用程序&#xff0c;例如 Microsoft Word…...

(免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设农产品销售管理系统。…...

centos更改yum源

1、更改yum源 阿里云/etc/yum.repos.d/CentOS-Base.repo 金山云/etc/yum.repos.d/cloud.repo vi /etc/yum.repos.d/cloud.repo 替换为 [base] nameCentOS-$releasever - Base mirrorlisthttp://mirrorlist.centos.org/?release$releasever&arch$basearch&repoos&…...

React-快速搭建开发环境

1.安装 说明&#xff1a;react-excise-01是创建的文件名 npx create-react-app react-excise-01 2. 打开文件 说明:we suggest that you begin by typing:下面即是步骤。 cd react-excise-01 npm start 3.显示...

算法随想录算法训练营第四十六天| 583. 两个字符串的删除操作 72. 编辑距离

583. 两个字符串的删除操作 题目&#xff1a;给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 思路&#xff1a;这题思路主要是求出 word1 字符串和 word2 字符串中的最长相同的子字符串&…...

vue源码分析(五)——vue render 函数的使用

文章目录 前言一、render函数1、render函数是什么&#xff1f; 二、render 源码分析1.执行initRender方法2.vm._c 和 vm.$createElement 调用 createElement 方法详解&#xff08;1&#xff09;区别&#xff08;2&#xff09;代码 3、原型上的_render方法&#xff08;1&#xf…...

Maven第三章:IDEA集成与常见问题

Maven第三章:IDEA集成与常见问题 前言 本章内容重点:了解如何将Maven集成到IDE(如IntelliJ IDEA或Eclipse)中,以及使用过程中遇到的常见的问题、如何解决,如何避免等,可以大大提高开发效率。 IEAD导入Maven项目 File ->Open 选择上一章创建的Maven项目 my-app查看po…...

数据结构—线性实习题目(二)5迷宫问题(栈)

迷宫问题&#xff08;栈&#xff09; #include <iostream>​ #include <assert.h> using namespace std;int qi1, qi2; int n; int m1, p1; int** Maze NULL; int** mark NULL;struct items {int x, y, dir; };struct offsets {int a, b;char* dir; };const int…...

Nginx 的配置文件(负载均衡,反向代理)

Nginx可以配置代理多台服务器&#xff0c;当一台服务器宕机之后&#xff0c;仍能保持系统可用。 cmd查找端口是否使用&#xff1a;netstat -ano Nginx出现403 forbidden #解决办法&#xff1a;修改web目录的读写权限&#xff0c;或者是把nginx的启动用户改成目录的所属用户&…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

Qwen系列之Qwen3解读:最强开源模型的细节拆解

文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...

Qt Quick Controls模块功能及架构

Qt Quick Controls是Qt Quick的一个附加模块&#xff0c;提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中&#xff0c;这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构&#xff0c;与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...

2025年全国I卷数学压轴题解答

第19题第3问: b b b 使得存在 t t t, 对于任意的 x x x, 5 cos ⁡ x − cos ⁡ ( 5 x t ) < b 5\cos x-\cos(5xt)<b 5cosx−cos(5xt)<b, 求 b b b 的最小值. 解: b b b 的最小值 b m i n min ⁡ t max ⁡ x g ( x , t ) b_{min}\min_{t} \max_{x} g(x,t) bmi…...