在我们的实际开发中,序列化和反序列化几乎无处不在,今天我们就来聊聊这个知识点。

1.序列化的概念

把对象转换为字节序列的过程称为对象的序列化。

序列化是将对象的状态转换为可存储或可传输格式的过程。对象在内存中一般以特定的数据结构(指针、引用、哈希表、链表等)存在,直接传输内存数据是不可靠的(不同机器架构不同、数据对齐不同、指针无意义等问题)。

通过对象的序列化,我们可以把对象的字节序列永久的保存到硬盘上,通常是存放在一个文件中;我们还可以在网络上传输对象的字节序列;简单来说,序列化就是让数据"离开内存,去旅行"。

在一些应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如,我们可以将应用中的数据持久化存储到文件中,下次程序启动时直接将数据恢复到内存中,这样就不需要重新初始化数据了。这在数据较大或初始化过程复杂时尤为方便。

在分布式系统中,远程方法调用(RMI)常常需要将对象通过网络传输到另一个JVM中。当a服务和b服务进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传输。发送方需要把这个java对象转换为字节序列,才能在网络上传输,接收方则需要把字节序列再恢复为java对象。

2.反序列化的概念

把字节序列恢复为对象的过程称为对象的反序列化。

把收到的字节流或文本格式数据,还原成内存中的对象或数据结构,供程序继续操作。比如从磁盘中读取一段json数据,把redis里缓存的对象取出来恢复成原始对象。

3.我们为什么需要序列化

我们来看一下常见的场景:

应用场景为什么需要序列化
网络通信TCP/UDP传输的数据必须是字节流,无法直接传对象
本地持久化把程序状态保存到磁盘,下次能恢复
跨平台数据交换不同系统、不同语言之间必须用标准格式
缓存系统Redis、Memcached存的是序列化后的对象
消息队列Kafka、RabbitMQ里的消息通常也是经过序列化的
RPC调用gRPC、Thrift调用远端服务需要将请求和响应序列化

4、常见的序列化格式对比

格式优点缺点典型应用
JSON人类可读、跨平台、广泛支持体积大、解析慢前后端接口、配置文件
XML结构复杂、可扩展性好体积更大、解析更慢SOAP服务、老系统
Protobuf体积小、速度快、强类型定义不易读、需要提前定义proto文件gRPC、分布式系统内部通信

5、如何实现序列化与反序列化

在java中,序列化和反序列化是通过实现Serializable接口来完成的。

1.实现Serializable接口

对于一个需要序列化的java类,必须实现Serializable接口:

image-20250921215336840.png

这个接口本身没有任何方法,它只是一个标记接口,用于告诉Java虚拟机这个类可以被序列化。

2. 使用 ObjectOutputStream 序列化对象

image-20250921215924133.png

image-20250921215951823.png

在这个例子中,我们将 user对象序列化并存储在本地文件 user.ser 中。

3. 使用 ObjectInputStream 反序列化对象

将序列化的文件恢复回对象(反序列化)时,可以使用 ObjectInputStream 类:

image-20250921220509195.png

在反序列化过程中,有时会遇到反序列化失败的情况,常见的原因之一是:serialVersionUID 不一致,每个序列化的类都会包含一个 serialVersionUID,它是唯一标识类版本的“身份证”。在反序列化时,Java虚拟机会检查对象的 serialVersionUID 与本地类的 serialVersionUID 是否匹配。如果不一致,Java会抛出 InvalidClassException 异常,表示反序列化失败。实验代码:

image-20250921220911603.png

原本是1的,但是我在序列化之后,将1改成了2:

image-20250921220945783.png

然后去执行反序列化,会抛出异常:

image-20250921221048116.png

所以,为了保证反序列化的顺利进行,建议在类定义时显式定义 serialVersionUID。

6、序列化的最佳实践

  • 显式声明 serialVersionUID:避免在类结构改变时导致反序列化失败。

  • 避免对敏感字段进行序列化:对于一些敏感信息(如密码),可以使用 transient 关键字修饰,防止这些字段被序列化。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]