IO流(4)- 序列化流与反序列化流
目录
1. 序列化流与反序列化流的基本介绍
2. 序列化流的基本用法?
3. 序列化流的作用?
4. 反序列化流的基本用法?
5. 反序列化流的作用
6. 序列化流与反序列化流使用时需要注意的细节(非常重要)
6.1 被序列化的JavaBean类必须实现 Serializable 接口,
6.2 javaBean类尽量在定义时加上"版本号"
6.3 transient 关键字的使用
6.4 序列化流得到的文件不要修改
1. 序列化流与反序列化流的基本介绍

如上图所示,序列化流与反序列化流也是IO流中会用到的一种高级流,也是用来包装基本流对象的,它们的继承关系如上图中所示。
序列化流是字节流的一种,它负责输出数据。
反序列化流也是字节流的一种,它负责输入数据。
2. 序列化流的基本用法?
如下图所示为序列化流的构造器,序列化流也是一个高级流,它的参数需要传递一个基本流对象;
序列化流地写方法也很简单,名为writeObject(),参数需要传递一个对象,如下所示;

我来简单给大家演示一下它的使用
(1)既然它是用来写对象的,我们就先创建一个JavaBean类,如下我定义了一个银行账户类
// 这里面要记住,一定要记得实现 Serializable 接口,否则会序列化失败
public class Account implements Serializable {// 账户idprivate Integer accountId;// 账户人名称private String accountName;// 账户密码private String accountPassword;@Overridepublic String toString() {return "Account{" +"accountId=" + accountId +", accountName='" + accountName + '\'' +", accountPassword='" + accountPassword + '\'' +'}';}public Integer getAccountId() {return accountId;}public void setAccountId(Integer accountId) {this.accountId = accountId;}public String getAccountName() {return accountName;}public void setAccountName(String accountName) {this.accountName = accountName;}public String getAccountPassword() {return accountPassword;}public void setAccountPassword(String accountPassword) {this.accountPassword = accountPassword;}
}
接着我们来到另一个测试类,创建一个 main 方法,测试序列化流的使用,我把注释也标注进去
public static void main(String[] args) {// 定义一个账户对象并赋予初始值Account account = new Account(101,"张三","123456");// 创建一个 ObjectOutputStream 的流对象ObjectOutputStream oos = null;try {// 对 oos 赋值// 将 account 的而对象的结果写道 account.txt 文件中去oos = new ObjectOutputStream(new FileOutputStream("user-service/account.txt"));// 将 account 对象写出oos.writeObject(account);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {// 保证给程序的健壮性,关闭之前先做判空操作,否则会空指针异常try {if (oos != null)oos.close();} catch (IOException e) {e.printStackTrace();}}}
我们运行此main 方法,在项目目录下会得到名为 account.txt 的文件,里面就存放着我们 account 对象的信息,我们打开查阅如下所示

可以看到,我们打开所看到的是一大堆乱码,这是为什么呢?
其实这是正常现象,序列化流可以把Java文件写到本地文件中去,通常情况下,写到本地文件的系列化流文件我们都是看不懂的,因为这本来就不是给我们看的,而是用于给程序看的。下面我们就此来引出序列化流的作用。
3. 序列化流的作用?
通过刚才的一个小例子,我们简单了解了序列化流的使用,也留下了一个问题。既然写出的文件看不懂,我们要他来做什么用呢?
怎么说呢,我举个最简单的例子,假如你电脑上有一个单机游戏,比如植物大战僵尸吧,大家不知道玩过没有,里面就有金币对吧,当我们不想玩了之后,关闭游戏游戏是会把我们的金币数额和所有的通关进度通过IO流的方式写到我们的本地磁盘上去的,当我们再次打开要玩的时候,它会再次读取到本地文件中的内容,将我们的金币数额和通关进度在读到内存中,我们就可以接着上次的进度游玩了。
游戏将金币数额与游戏进度保存的这个过程,就和序列化很相似;
游戏会将金币数额和游戏进度再次读取到内存中去,就和反序列化有些相似。
那么现在就有一个问题了,如果你是这个游戏的设计者,你在序列化的时候,序列化的得到的游戏进度文件希望玩家能看懂能修改吗?肯定不能吧,如果任意玩家都可以看得懂并且能修改序列化得到的游戏进度文件,那和开外挂有什么区别?我直接把金币改成9999999999,不用再打金币了。
这样举例子各位应该就有些明白了吧!
这也只是序列化流的用途之一,序列化流与反序列化流的用途还有很多,比如互联网传输用户数据,我们通常都是采用二进制传输,你总不能将数据原样进行传输吧,特别是如果传输的数据带有敏感信息,比如账户名称密码,银行账户密码,这些是绝对不能让用户看得懂可以修改的。一旦被不法人员拦截攻击,造成的损失会非常大,因此就可以使用我们的序列化流,将要传输的数据进行序列化处理。
4. 反序列化流的基本用法?
如上图所示,即为反序列化流的构造方法与常用方法,我们来简单的测试一下吧
如下代码,我们把刚才序列化的 account 对象在反序列化回来,我们试一试
public static void main(String[] args) {// 定义一个账户对象并赋予初始值Account account = new Account(101,"张三","123456");// 创建一个 ObjectOutputStream 的流对象ObjectInputStream ois = null;try {// 对 ois 赋值// 将 account.txt 文件中保存的对象数据再读出来ois = new ObjectInputStream(new FileInputStream("user-service/account.txt"));// 将 account 对象读出Object o = ois.readObject();// 输出独到的 account 对象数据System.out.println(o);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {// 保证给程序的健壮性,关闭之前先做判空操作,否则会空指针异常try {if (ois != null)ois.close();} catch (IOException e) {e.printStackTrace();}}}
运行 main 方法,就可以得到如下图所示的结果

可以看到,原本我们创建的对象 account 就又被我们读取出来了,而且还能还得懂。
5. 反序列化流的作用
通过刚才的演示与对序列化流作用的说明,这里就不需要我在多做解释了,总而言之就一句话。
反序列化流可以将序列化的数据载读取为我们可以看的懂可以操作的原本模样。
6. 序列化流与反序列化流使用时需要注意的细节(非常重要)
6.1 被序列化的JavaBean类必须实现 Serializable 接口,
我们可以来看一下 Serializable 接口的源码,如下所示

可以看到,再序列化流接口中,没有任何东西,这种借口有一个专业名词,被称为标记型接口,备有实际含义,只是作为一个标记,只有被标记的JavaBean类才能参与序列化。如果不实现该接口,就会报错,这里应该也不用多解释,各位在做 Spring 项目的时候,通常都会在javaBean类中是实现 Serializable 接口,因为我们项目运行时的数据就是在互联网之间进行传输的,所以需要实现 Serializable 接口。
6.2 javaBean类尽量在定义时加上"版本号"
有些小伙伴可能不知道,当你对一个JavaBean类添加了 Serializable 接口要参与序列化时,该JavaBean类是有版本号的,如果你对javaBean类做了修改,版本号也会修改,一旦版本号修改,再序列化与反序列化时,就会出现错误,因此我们最好在JavaBean类中添加上版本号,这个我们可以借鉴 ArrayList 的源码设计哦,我们来看一下

在ArrayList 源码中我们可以发现,它也定义了一个版本号,而且各位要注意,这个版本号变量不是乱起的,必须是 serialVersionUID,不能是别的;如果不添加 serialVersionUID 变量,我们的javaBean类一旦发生修改,版本号也会修改,就是因为版本号不一致导致无法序列化成功,因此我们需要让版本号使用为一个,就需要定义为 final,又因为它是该类属性中共享属性,需要定义为 static ,serialVersionUID 最好定义为 long 类型。
因此,在定义版本号时,最好定义为
private static final long serialVersionUID = ?
至于取什么值,无所谓,只要遵守该变量的定义原则即可。
6.3 transient 关键字的使用
还有一些时候,我们不想让JavaBean 类中的一些变量参与序列化与反序列化,该怎么办呢?
这个时候就可以用到我们的 transient 关键字。
被 transient 关键字修饰的变量,不会参与到类的序列化与反序列化,我来给大家演示一下,还拿刚才的例子举例说明,如下图所示

我把 accountpassword 账户密码这一属性不参与数列化,因为太不安全,我们就可以在JavaBean类中 该变量前面加上 transient 关键字,一旦加上,就不会参与序列化,我们再回到 main 方法作出修改
public static void main(String[] args) {// 定义一个账户对象并赋予初始值Account account = new Account(101,"张三","123456");// 创建一个 ObjectOutputStream 的流对象ObjectOutputStream oos = null;// 创建一个 ObjectOutputStream 的流对象ObjectInputStream ois = null;try {// 对 oos 赋值oos = new ObjectOutputStream(new FileOutputStream("user-service/account.txt"));// 对 ois 赋值// 将 account.txt 文件中保存的对象数据再读出来ois = new ObjectInputStream(new FileInputStream("user-service/account.txt"));// 先将 account 对象写出oos.writeObject(account);// 再将 account 对象读出Object o = ois.readObject();// 输出独到的 account 对象数据System.out.println(o);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {// 保证给程序的健壮性,关闭之前先做判空操作,否则会空指针异常try {if (oos != null)oos.close();if (ois != null)ois.close();} catch (IOException e) {e.printStackTrace();}}}
然后再次运行得到如下结果

可以发现,即便我们初始为 accountPassword 赋值,但因为添加了 transient 关键字的缘故,他就不会参与序列化与反序列化,系统胡自动给一个默认值为 null。
各位小伙伴有些时候再看源码时的时候可能也见过 transient 关键字,就是用来做标记的,不让其被标记的变量参与序列化。
6.4 序列化流得到的文件不要修改
我们在通过序列化得到的文件,虽然是一堆乱码看不懂,但时不要轻易去修改,因为一旦修改,再次反序列化时,程序就读不出来了,会报错,这也是序列化流中需要注意的一个点哦!
相关文章:
IO流(4)- 序列化流与反序列化流
目录 1. 序列化流与反序列化流的基本介绍 2. 序列化流的基本用法? 3. 序列化流的作用? 4. 反序列化流的基本用法? 5. 反序列化流的作用 6. 序列化流与反序列化流使用时需要注意的细节(非常重要) 6.1 被序列化的…...
人工智能如何应对 DevOps 监控和可观测性挑战
自 ChatGPT 横空出世之后,AIGC 已成为不可逆转的时代浪潮。在之前的文章中,我们介绍了DevOps 领域中AI的用例,需要回顾可以点击下方链接。在本篇文章中,我将简单聊聊人工智能(AI)如何通过分析日志和指标来预…...
数字化新时代,VR全景拍摄与制作
导语: 随着科技的飞速发展,数字化图片正在引领新的时代潮流。在这个数字化图片的新时代,VR全景拍摄与制作技术正以其独特的特点和无限的优势,成为数字影像领域的一颗璀璨明星。让我们深入了解VR全景拍摄与制作的特点和优势&#…...
uniapp 权限说明
android.permission.ACCESS_CHECKIN_PROPERTIES 访问登记属性 读取或写入登记check-in数据库属性表的权限 android.permission.ACCESS_COARSE_LOCATION 获取错略位置 通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米 android.permission.ACCESS…...
3D Web轻量化渲染开发工具HOOPS Communicator是什么?
HOOPS Communicator是Tech Soft 3D旗下的主流产品之一,具有强大的、专用的高性能图形内核,是一款专注于基于Web端的高级3D工程应用程序。由HOOPS Server和HOOPS Web Viewer两大部分组成,提供了HOOPS Convertrer、Data Authoring的模型转换和编…...
心法利器[93] | 谈校招:技术面
心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。 2022年新一版的文章合集已经发布,累计已经60w字了,获取方式看这里&…...
excel英语翻译让你的数据更容易被理解
从前有一个名叫小明的办公室职员,他每天都要处理大量的数据和报表。然而,由于工作需要,他经常收到来自不同国家的Excel表格,这些表格上的内容都是用各种各样的语言编写的,让他很难理解其中的意思。这时,小明…...
RK3588S之CPU--benchmark(二)
目录 一、引言 二、benchmark测试工具 ------>2.1、Geekbench ------------>2.1.1、下载移植 ------------>2.1.2、跑分结果 ------------>2.1.3、跑分榜 ------>2.2、Spec06 ------------>2.2.1、spec06介绍 ------------>2.2.2、下载移植(包含…...
入侵检查基础
一、结合以下问题对当天内容进行总结 1. 什么是IDS? 2. IDS和防火墙有什么不同? 3. IDS工作原理? 4. IDS的主要检测方法有哪些详细说明? 5. IDS的部署方式有哪些? 6. IDS的签名是什么意思?签名过滤器有什么…...
JAVA开发工具-maven的安装与配置(最新最详细教程)
引言 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具 软件。 Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较 高的可重用性,所以常常用两…...
linux系统编程重点复习--进程的控制
目录 1 复习目标 2 进程相关概念 2.2 并行和并发 2.3 PCB-进程控制块 2.4 进程状态(面试考) 3 创建进程 3.2 ps命令和kill命令 3.3 getpid/getppid 3.4 练习题 4 exec函数族 4.1 函数作用和函数介绍 4.1.1 execl函数 4.1.2 execlp函数 4.2 exec函数族原理介绍 4.3 …...
12-1_Qt 5.9 C++开发指南_自定义插件和库-自定义Widget组件(提升法(promotion)创建自定义定制化组件)
当UI设计器提供的界面组件不满足实际设计需求时,可以从 QWidget 继承自定义界面组件。 有两种方法使用自定义界面组件: 一种是提升法(promotion),例如在8.3 节将一个QGraphicsView组件提升为自定义的 QWGraphicsView 类,提升法用…...
【软件测试学习】—软件测试的基本认识(一)
【软件测试学习】—软件测试的基本认识(一) 文章目录 【软件测试学习】—软件测试的基本认识(一)一、什么是软件测试二、软件测试的目的三、测试的原则四、测试的标准五、测试的基本要求六、bug的由来七、测试的流程八、开发模式九…...
Unity AI项目笔记
一、创建虚拟环境 在开始进行Unity AI项目之前,首先需要设置一个适当的虚拟环境。以下步骤将会指导你如何创建: 下载Python 3.7。下载Anaconda 2020.11。可以在清华大学开源软件镜像站找到镜像资源:https://mirrors.tuna.tsinghua.edu.cn/a…...
如何在地图上寻找峨眉山零公里的龙洞湖
爬峨眉山的需要,住在零公里附近。 据说这附近有个好玩的地方叫龙洞湖,我们住得远,想步行去看看。拿出地图,搜龙洞湖,尴尬了。搜不到具体位置。细想,人家整个村就叫龙洞村,地图上居然没有标识&a…...
cloudstack平台host加入后,显示CPU speed为0GHz
一、环境说明 操作系统:openEuler 22.03CPU:Kunpeng-920,arm v8cloudstack:4.18libvirtd:6.2.0 二、问题描述 cloudstack平台初始化完成后,第一次加入host,系统虚拟机一直无法正常创建&#…...
创新技术应用,提升企业图文档管理水平的新思路
信息爆炸和数字化发展的时代,企业图文档管理显得尤为重要。传统的纸质文件管理方式已经无法满足企业高效、安全、便捷管理的需求。因此,创新技术的应用成为了提升企业图文档管理水平的必然选择。PDM(产品数据管理)与BOM࿰…...
网络安全 Day22-mariadb数据库用户管理
数据库用户管理 1. mariadb数据库用户管理2. mariadb数据库用户授权3. 用户回收授权4. 使客户端连接数据库 1. mariadb数据库用户管理 用户的格式: 用户主机范围 合起来才算一个用户授权主机范围 只能从本机访问: localhost或127.0.0.1或10.0.0.166(指定IP)授权整个网段: 授权…...
SERDES关键技术
目录 一、SERDES介绍 二、SERDES关键技术 2.1 多重相位技术 2.2 线路编解码技术 2.2.1 8B/10B编解码 2.2.2 控制字符(Control Characters) 2.2.3 Comma检测 2.2.4 扰码(Scrambling) 2.2.5 4B/5B与64B/66B编解码技术 2.3 包传…...
小程序如何上传商品图片
了解如何在小程序商城中上传商品图片是非常重要的,因为商品图片的质量和展示效果直接影响到用户对商品的购买决策。下面,我将介绍怎么在小程序上传产品图片的方法和注意事项。 1. 图片准备:在上传商品图片之前,首先要准备好商品图…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
