Java序列化与反序列化

概念:

  • 序列化:将对象转化成字节序列
  • 反序列化:将字节序列转化成对象

在这里插入图片描述

在Java中,通过实现Serializable接口来声明一个类是可序列化的。被序列化的类及其内部所有引用对象,都必须实现Serializable接口,否则序列化过程会抛出异常。

作用:

  • 数据传输

在网络传输中,将对象序列化成字节流方便传输,等收到数据后再反序列化成对象做业务处理

  • 数据持久化

对象是存储在JVM中的堆区,JVM停止运行,对象也就不存在了,将对象序列化成字节流后可写入文件或数据库进行存储,JVM新启动后又可以读取字节序列进行反序列化成对象。

  • 进程间通信

在进程间通信中,序列化可以将一个对象转换为字节流,使其可以在不同的进程之间进行传递。


举例:

先定义一个Person类,实现Serializable接口:

// 需要实现Serializable接口才能被序列化
@Data
@AllArgsConstructorpublic class Person implements Serializable{private String name;private int age;
}

写测试类:

import java.io.*;public class SerializationExample {public static void main(String[] args) {// 创建一个Person对象Person person = new Person("Alice", 25);// 序列化对象到文件try {FileOutputStream fileOut = new FileOutputStream("person.ser");ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);objectOut.writeObject(person);objectOut.close();   //偷个懒,就不在finally中关了fileOut.close();System.out.println("对象已成功序列化并保存到文件中");} catch (IOException e) {e.printStackTrace();}// 从文件反序列化对象Person deserializedPerson = null;try {FileInputStream fileIn = new FileInputStream("person.ser");ObjectInputStream objectIn = new ObjectInputStream(fileIn);deserializedPerson = (Person) objectIn.readObject();objectIn.close();fileIn.close();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}// 打印反序列化后的对象if (deserializedPerson != null) {System.out.println("对象已成功反序列化:");System.out.println("姓名:" + deserializedPerson.getName());System.out.println("年龄:" + deserializedPerson.getAge());} else {System.out.println("反序列化失败");}}
}

运行:

在这里插入图片描述

ObjectInputStream类用于从字节流中读取对象,ObjectOutputStream类用于将对象写入字节流。 这两个类是Java提供的用于实现序列化和反序列化的核心类。


关于序列化版本号:

serialVersionUID,序列化版本号,用来标识类的版本,确保反序列化过程中所使用的类与序列化时所使用的类是兼容的。

举个例子,上面的Person类,我前脚序列化一个Person对象到文件,你后脚把这个类改了,我再反序列化回对象时,这个Person就对不上了:

deserializedPerson = (Person) objectIn.readObject();

整个流程大概是:

  • 如果不指定serialVersionUID,Java将根据类的内部特征(例如成员变量、方法等)计算出一个默认的序列化版本号。

  • 这个类发生修改,则自动生成的序列化版本号可能会不一致

  • Java会认为类的版本不兼容

  • 在反序列化时抛出InvalidClassException异常

想解决这个问题,可以显式地定义serialVersionUID并指定一个固定的版本号,而不是让它自动生成。

public static final long serialVersionUID = 1L;

Externalizable接口:

除了实现Serializable接口外,类还可以实现Externalizable接口。

实现Externalizable接口可以定制对象的序列化和反序列化过程,但需要手动实现writeExternal()和readExternal()等方法。

copy个例子:

public class TextBean implements Externalizable {private Integer id;private String name;private Date date;//可以自定义决定那些需要序列化@Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeInt(id);out.writeObject(name);out.writeObject(date);}//可以自定义决定那些需要反序列化@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {this.id = in.readInt();this.name = (String) in.readObject();this.date = (Date) in.readObject();}//省去getter和setter方法和toString
}

补充:

transient关键字

  • 用于修饰类的成员变量,表示不参与序列化过程
  • 被transient修饰的成员变量在序列化时会被忽略,反序列化后会被赋予其数据类型的默认值

当你的类的某些成员变量是不可序列化的(比如引用没有实现Serializable接口的对象),你需要在声明这些变量时使用transient关键字,以便在序列化时忽略它们。


Tips:

IDEA中,在类名上按Alt+Enter,可加序列化版本号。

在这里插入图片描述

如果没有这个选项,在这儿配置一下:

在这里插入图片描述

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

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

相关文章

隐藏cobaltstrike服务器-nginx反向代理

隐藏nginx版本 编辑/etc/nginx/nginx.conf 取消server_tokens off 前面的注释 http转发80端口 编辑/etc/nginx/sites-enabled/default ## # You should look at the following URLs in order to grasp a solid understanding # of Nginx configuration files in order to …

Spring Boot 属性加载原理解析

基于Spring Boot 3.1.0 系列文章 Spring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Spring Boot 系统初始化器详解Spring Boot 监听器详解Spring Boot banner详解Spring Boot 属性配置解析Spring Boot 属性加载原理解析 在《Spring Boot 框架整体启动流程详…

计算机视觉 - 理论 - 从卷积到识别

计算机视觉 - 理论入门 前言一,导论:二,卷积:图像去噪:常值卷积:高斯卷积:椒盐去噪:锐化程度: 三,边缘检测:图像信号导数:求导算子:图…

如何用rust实现一个异步channel

目录 前言思路实现功能代码实现 测试先引测试版包测试代码结果与分析思考 尾语 前言 使用通信来共享内存,而不是通过共享内存来通信 上面这句话,是每个go开发者在 处理多线程通信时 的座右铭,go甚至把实现这个理念的channel直接焊在编译器里&…

macOS编译AirMap开源全景图源码image-processing

1.克隆源码 git clone --recursive https://github.com/airmap/image-processing.git 2. 使用CLion打开CMakeLists.txt并做为工程打开 2.默认配置名为Default,可修改,下面的所有配置项都可改 3.点击OK后会自动生成

8 系统定时器(Systick)(STM32HAL库)

目录 系统定时器(Systick) SysTick定时器特性介绍 SysTick定时器的功能 SysTick定时器寄存器介绍 Systick定时器的使用 系统定时器(Systick) SysTick定时器特性介绍 计数宽度: 24bit来存储数据,2^24…

使用影刀RPA拆分excel数据

首先,要使程序有一定的兼容性,即增加互动性,认为选择要拆分的文件和拆分的依据列,可以利用影刀中的‘打开选择对话框’和‘打开输入对话框’来实现,这样一来便不用考虑待拆分excel的路径问题获取1中选择的依据拆分列&a…

企业构建知识库方案

AI模型理解误区:百万成本微调垂直行业达模型VS低成本建立企业专属知识库或ai助理_哔哩哔哩_bilibili

基于TensorFlow和Keras的狗猫数据集的分类实验

文章目录 前言一、环境配置1、anaconda安装2、修改jupyter notebook工作目录3、配置TensorFlow、Keras 二、数据集分类1、分类源码2、训练流程 三、模型调整1.图像增强2、网络模型添加dropout层 四、使用VGG19优化提高猫狗图像分类1、构建网络模型2、初始化一个VGG19网络实例3、…

课程20:API项目重构

🚀前言 本文是《.Net Core从零学习搭建权限管理系统》教程专栏的课程(点击链接,跳转到专栏主页,欢迎订阅,持续更新…) 专栏介绍:以实战为线索,基于.Net 7 + REST + Vue、前后端分离,不依赖任何第三方框架,从零一步一步讲解权限管理系统搭建。 专栏适用于人群:We…

详解如何使用nvm管理Node.js多版本

目录 NVM进行NodeJS多版本管理 背景 安装步骤 1. 下载nvm安装包 2. 安装nvm 使用步骤 下载nodejs 切换版本nodejs ​编辑 常用命令 NVM进行NodeJS多版本管理 背景 有的时候开发环境需要多个NodeJS的版本,这个时候就可以用NVM进行管理。 安装步骤 1. 下载n…

云原生之深入解析Flink on k8s的运行模式与实战操作

一、概述 Flink 核心是一个流式的数据流执行引擎,并且能够基于同一个 Flink 运行时,提供支持流处理和批处理两种类型应用。其针对数据流的分布式计算提供了数据分布,数据通信及容错机制等功能。Flink 官网不同版本的文档flink on k8s 官方文…