序列化-Serializable和Parcelable

2023-11-30 23:36

本文主要是介绍序列化-Serializable和Parcelable,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Serializable

在Android开发中,Serializable是一种用于将对象序列化和反序列化的接口。它是Java的标准序列化方式,可以在任何Java平台上使用。

下面是使用Serializable进行对象序列化的步骤:

  1. 在要序列化的类中实现Serializable接口:在类定义上实现Serializable接口。
import java.io.Serializable;public class MyObject implements Serializable {private int id;private String name;// 构造函数public MyObject(int id, String name) {this.id = id;this.name = name;}// 省略get和set
}
  1. 序列化对象:创建一个输出流,并将对象写入该输出流。
MyObject myObject = new MyObject(1, "Example");try {FileOutputStream fileOut = new FileOutputStream("path/to/file");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(myObject);out.close();fileOut.close();
} catch (IOException e) {e.printStackTrace();
}
  1. 反序列化对象:创建一个输入流,并从输入流中读取对象。
MyObject myObject = null;try {FileInputStream fileIn = new FileInputStream("path/to/file");ObjectInputStream in = new ObjectInputStream(fileIn);myObject = (MyObject) in.readObject();in.close();fileIn.close();
} catch (IOException | ClassNotFoundException e) {e.printStackTrace();
}

通过实现Serializable接口,你可以使用Java的标准序列化机制对对象进行序列化和反序列化。但需要注意的是,尽管Serializable是方便的,但它的序列化过程相对较慢,并且会消耗大量的内存。因此,在Android开发中,如果性能要求较高,建议使用Parcelable接口进行对象序列化。

原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同时才能够正常的被反序列化。serialVersionUID的详细工作机制是这样的:序列化的时候系统会把当前类的serialVersionUID写入序列化的文件中(也可能是其他的中介),当反序列化的时候系统会去检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功反序列化,否则就说明当前类和序列化的类相比发生了某些变换

给serialVersionUID制定为1L或者采用Eclipse根据当前类结构去生成的hash值,这两者并没有本质区别。

  • 静态成员变量属于类不属于对象,所以不会参与序列化过程
  • 其次用transient关键字标记的成员变量不参与序列化过程

Parcelable接口

在Android开发中,Parcelable是一种用于将对象序列化和反序列化的接口。它比Java中的Serializable更高效,因为它是在内存中直接操作对象的字段,而不会经过IO流的序列化和反序列化过程。

下面是使用Parcelable进行对象序列化的步骤:

  1. 实现Parcelable接口:在要序列化的类中实现Parcelable接口,并实现其中的方法。Parcelable接口包括两个核心方法:writeToParcel()createFromParcel()writeToParcel()方法用于将对象的字段写入Parcel对象,createFromParcel()方法用于从Parcel对象中读取字段并创建对象。
public class MyObject implements Parcelable {private int id;private String name;// 构造函数public MyObject(int id, String name) {this.id = id;this.name = name;}protected MyObject(Parcel in) {id = in.readInt();name = in.readString();}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(id);dest.writeString(name);}@Overridepublic int describeContents() {return 0;}public static final Creator<MyObject> CREATOR = new Creator<MyObject>() {@Overridepublic MyObject createFromParcel(Parcel in) {return new MyObject(in);}@Overridepublic MyObject[] newArray(int size) {return new MyObject[size];}};
}
  • 序列化对象:将对象序列化为Parcel对象。
MyObject myObject = new MyObject(1, "Example");
Parcel parcel = Parcel.obtain();
myObject.writeToParcel(parcel, 0);
  • 反序列化对象:从Parcel对象中读取字段并创建对象。
parcel.setDataPosition(0);
MyObject myObject = MyObject.CREATOR.createFromParcel(parcel);

这样,你就可以使用Parcelable接口来实现Android中的对象序列化和反序列化了。注意,要确保对象的字段顺序一致,以便正确地读取和写入Parcel对象。另外,Parcelable只适用于Android平台,如果需要在不同平台之间进行对象序列化,考虑使用其他的序列化方式,如JSON(有很便捷的api进行读入读出)

Parcelable的方法说明:

方法功能标记位
createFromParcel(Parcel in)从序列化的对象中创建原始对象
newArray[int size]创建指定长度的原始对象数组
User(Parcel in)从序列化的对象中创建原始对象
write ToParcel(Parcel out, int flags)将当前对象写入序列化结构中,其中flags标识有两种值0或1(参见右侧标记位)。为1时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0PARCELABLE_WRITE_RETURN_VALUE
describeContents返回当前对象的内容描述。如果含有文件描述符,返回1(参见右侧标记位),否则返回0,几乎所有的情况都返回0CONTENTS_FILE_DESCRIPTOR
  • 系统已经为我们提供了许多实现了Parcelable接口的类,它们都是可以直接序列化的,比如Intent、Bundle、Bitmap等,同时List和Map也可以序列化,前提是它们里面的每个元素都是可序列化的。

如何选取

Serializable是Java中的序列化接口,其使用起来简单但是开销很大,序列化和反序列化需要大量I/O操作。而Parceleble是Android中的序列化方式,因此更适合在Android平台上,缺点是麻烦,但是效率高,这是Android推荐的序列化方式,所以我们要首选Parcelable。Parcelable主要用在内存序列化上,通过Parcelable将对象序列化到存储设备中或者将对象序列化之后通过网络传输,但是过程稍显复杂,因此在这两种情况下建议大家使用Serializable。

这篇关于序列化-Serializable和Parcelable的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/438962

相关文章

Serializable的好处

任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方。也可以用管道来传输到系统的其他程序中。这样子极大的简化了类的设计。 import java.io.Serializable;import java.util.Arrays;import java.util.HashMap;import java.util.Map;public

Python---文件IO流及对象序列化

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 前文模块中提到加密模块,本文将终点介绍加密模块和文件流。 一、文件流和IO流概述         在Python中,IO流是用于输入和输出数据的通道。它可以用于读取输入数据或将数据写入输出目标。IO流可以是标准输入/输出流(stdin和stdout),也可以是文件流,网络流等。

jquery 表单序列化

jQuery序列化表单的方法总结 现在这里贴出案例中静态的html网页内容: <!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><title>Title</title><script src="../js/jquery-3.2.1.js"></script></head><body><form method="post"

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1)getTransletInstance2)defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码,但由于defineClas

Spring之——整合Redis序列化方式StringRedisSerializer、FastJsonRedisSerializer和KryoRedisSerializer

当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。 Spring Data JPA为我们提供了下面的Serializ

DTO类实现Serializable接口的重要性

所谓序列化,简单一点理解,就是将对象转换成字节数组,反序列化是将字节数组恢复为对象。凡是要在网络上传输的对象、要写入文件的对象、要保存到数据库中的对象都要进行序列化。Java对象是无法直接保存到文件中,或是存入数据库中的。如果要保存到文件中,或是存入数据库中,就要将对象序列化,即转换为字节数组才能保存到文件中或是数据库中。文件或者数据库中的字节数组拿出来之后要转换为对象才能被我们识别,即反序列化。

使用 `readResolve` 防止序列化破坏单例模式

单例模式是一种设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点。在 Java 中,我们常常通过私有化构造方法和提供静态访问方法来实现单例。然而,尽管这些手段可以有效防止类的实例化,反射和序列化依然能够破坏单例模式的唯一性。本文将重点讲解序列化如何破坏单例模式,以及如何通过 readResolve 方法来防止这种破坏。 1. 序列化和反序列化 序列化 是指将对象的状态转换为字节

他来了他来了,Hadoop序列化和切片机制了解一下?

点击上方蓝色字体,选择“设为星标” 回复”面试“获取更多惊喜 切片机制 一个超大文件在HDFS上存储时,是以多个Block存储在不同的节点上,比如一个512M的文件,HDFS默认一个Block为128M,那么1G的文件分成4个Block存储在集群中4个节点上。 Hadoop在map阶段处理上述512M的大文件时分成几个MapTask进行处理呢?Hadoop的MapTask并行度与数据切片有有关系

【Linux】自定义协议与序列化和反序列化

一、自定义协议 1.1 自定义报文格式        在前面的博客中,我们可以知道在TCP协议中,面向的是字节流;而UDP协议中面向的是数据报。因此,在手写简单的TCP和UDP服务器中,所使用的是接收函数和发送函数不同。因此,在TCP协议中,我们需要分清楚一个完整的报文,并将其分离出来,因此,我们应该如何进行分离出一个完整的报文呢??        如果一个报文中什么标志也没有,那么必然是不

java 中rmi 服务的搭建与测试,java rmi 其实是加载远程的序列化后的java对象到本地 进行执行,所以注意rmi的远程代码执行漏洞。

经测试,在客户端调用服务端的方法时,也会会打印HelloServiceImpl中的 System.out.println的内容,所以可以证明会加载远程的HelloServiceImpl类在本地执行!!! rmi 客户端与服务端之间 传输的是序列化后的类示例对象,然后在客户端在反序列化生成对象,并初始化调用构造方法。 ldap 协议也会造成本地执行远程class文件的问题,不通与rmi,ldap