Java序列化
Java序列化
简单来说:
序列化是将对象的状态信息转换为可以存储或传输的形式(如字节序列)的过程。在 Java 中,通过序列化可以把一个对象保存到文件、通过网络传输到其他地方或者存储到数据库等。最直接的原因就是某些场景下需要使用这种数据状态,像网络中不能传输数据,某些存储场景。在java中常见使用,就是实现Serializable接口,而不想被序列化的字段处理方法使用transient关键字就可以了
推荐文章:为什么网络中不能直接传输数据
为什么在网络中不能直接传输数据_在网络通信中,除了文本和二进制数据,其他的数据都无法传输-CSDN博客
1. Java 中序列化的定义与作用
-
定义:序列化是将对象的状态信息转换为可以存储或传输的形式(如字节序列)的过程。在 Java 中,通过序列化可以把一个对象保存到文件、通过网络传输到其他地方或者存储到数据库等。例如,在分布式系统中,一个对象可能需要从一个节点传输到另一个节点,此时就需要将对象序列化。
-
原理:Java 序列化机制会自动处理对象的成员变量。当对一个对象进行序列化时,Java 会递归地将对象的非静态和非瞬态(
transient)成员变量转换为字节序列。这些字节序列包含了对象的类型信息和成员变量的值等内容。例如,对于一个包含姓名和年龄的Person类对象,序列化后字节序列会包含表示Person类的信息以及姓名和年龄的值的信息。 -
应用场景:
-
持久化存储:将对象保存到文件系统中,以便以后可以恢复对象的状态。例如,游戏中的玩家存档,玩家的角色信息(等级、装备等)可以通过序列化存储到本地文件,下次游戏时再读取并恢复。
-
网络传输:在分布式应用或远程调用(如 Java RMI)中,对象需要在不同的主机之间传输。例如,在一个基于微服务架构的电商系统中,订单信息对象可能需要从订单服务传输到库存服务,这就需要对订单信息对象进行序列化。
-
2. 不想被序列化的字段处理方法(使用transient关键字)
-
transient关键字的作用:当一个成员变量被声明为transient时,在序列化过程中这个变量将不会被包含在序列化后的字节序列中。例如,对于一个包含密码字段的User类,如果不想将密码序列化(因为安全原因),可以将密码字段声明为transient。 -
示例代码:
import java.io.Serializable;class Student implements Serializable {private String name;private transient int score;public Student(String name, int score) {this.name = name;this.score = score;}public String getName() {return name;}public int getScore() {return score;}}-
假设有一个
Student类,其中有一个成绩字段不想被序列化。
-
- 在这个例子中,`Student`类实现了`Serializable`接口,表示这个类的对象可以被序列化。`score`字段被声明为`transient`,所以当对`Student`对象进行序列化时,`score`字段的值不会被保存到序列化后的字节序列中。在反序列化时,`transient`字段会被初始化为默认值(对于基本类型,如`int`,默认值为0)。
3. 为什么使用序列化
对象持久化保存
-
在很多应用场景中,需要将对象的状态长期保存下来。例如,在一个企业级的资源管理系统中,用户的配置信息、系统的状态快照等都需要保存到文件或者数据库中,以便在下次启动程序或者系统恢复时能够重新加载这些信息。序列化提供了一种简单有效的方式来将对象转换为字节序列,这样就可以方便地存储到磁盘上。如果没有序列化,要将复杂的对象存储起来会非常复杂,可能需要手动将每个属性的值逐个提取出来并按照特定的格式写入文件,而序列化机制自动完成了这个复杂的过程。
网络通信的需要
-
网络确实不能直接传输像 Java 对象这种复杂的数据结构。网络通信协议通常是基于字节流或者消息包来传输数据的。当需要在不同的计算机系统或者进程之间传递对象时,就必须先将对象序列化。例如,在一个分布式的微服务架构中,一个服务需要调用另一个服务的方法并传递一些业务对象作为参数,这些对象必须被序列化后通过网络传输到目标服务,目标服务再将字节序列反序列化回对象,这样才能进行正常的业务处理。
跨平台和跨语言交互
-
序列化后的字节序列可以在不同的平台和语言环境下进行传输和处理。有些序列化格式(如 JSON、XML)是跨语言兼容的。例如,一个 Java 服务可以将一个对象序列化为 JSON 格式的字节序列,这个字节序列可以被 Python 服务接收并反序列化,这样就实现了不同语言编写的服务之间的交互。这种跨平台和跨语言的特性使得序列化在分布式系统和异构系统集成中非常重要。
缓存系统的应用
-
在缓存系统中,对象经常需要被存储和检索。序列化允许将对象以一种适合缓存存储的形式(如字节序列)存入缓存中。例如,在一个 Web 应用的缓存系统中,经常需要缓存一些复杂的业务对象(如用户信息、商品详情等),通过序列化可以方便地将这些对象存入像 Redis 这样的缓存中,当需要使用时再反序列化出来,提高了系统的性能和响应速度。
4. 怎么序列化
-
实现
Serializable接口-
接口介绍:在 Java 中,要使一个类可序列化,首先要让这个类实现java.io.Serializable接口。这个接口是一个标记接口,没有任何方法需要实现,它的作用是告诉 Java 虚拟机(JVM)这个类的对象可以被序列化。例如,假设有一个简单的Person类,包含姓名和年龄两个属性:
import java.io.Serializable;class Person implements Serializable {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}}
-
- **注意事项**:实现`Serializable`接口只是第一步,当类的结构发生变化(如添加或删除成员变量、修改成员变量的类型等)时,可能会影响序列化和反序列化的兼容性。为了更好地控制序列化过程,还可以定义一个`serialVersionUID`(序列化版本号)。这个版本号是一个`long`型的常量,用于标识类的序列化版本。如果在反序列化时,类的`serialVersionUID`与序列化时的版本号不一致,可能会导致`InvalidClassException`异常。例如,可以在`Person`类中添加版本号:```javaimport java.io.Serializable;class Person implements Serializable {private static final long serialVersionUID = 1L;// 后续代码同前}
-
使用
ObjectOutputStream进行序列化-
基本步骤:要将一个对象序列化到文件中,可以使用ObjectOutputStream类。首先创建一个文件输出流(FileOutputStream),然后将其包装成ObjectOutputStream
。接着,使用ObjectOutputStream的writeObject方法将对象写入到输出流中。例如,将Person对象序列化到文件:
import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.io.IOException;public class SerializeExample {public static void main(String[] args) {try {Person person = new Person("Alice", 30);FileOutputStream fileOut = new FileOutputStream("person.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(person);out.close();fileOut.close();System.out.println("对象已序列化到文件");} catch (IOException e) {e.printStackTrace();}}}
-
- **工作原理**:`ObjectOutputStream`在序列化对象时,会递归地处理对象的非静态和非瞬态(`transient`)成员变量。它会将对象的类型信息和成员变量的值按照特定的格式转换为字节序列,并写入到输出流中。如果对象的成员变量也是可序列化的对象,`ObjectOutputStream`会同样地对这些成员变量进行序列化。3. **从序列化数据中恢复对象(反序列化)**- **基本步骤**:使用`ObjectInputStream`类从序列化的数据中恢复对象。首先创建一个文件输入流(`FileInputStream`),然后将其包装成`ObjectInputStream`。接着,使用`ObjectInputStream`的`readObject`方法从输入流中读取对象。例如,从之前序列化的文件中读取`Person`对象:```javaimport java.io.FileInputStream;import java.io.ObjectInputStream;import java.io.IOException;public class DeserializeExample {public static void main(String[] args) {try {FileInputStream fileIn = new FileInputStream("person.ser");ObjectInputStream in = new ObjectInputStream(fileIn);Person person = (Person) in.readObject();in.close();fileIn.close();System.out.println("姓名:" + person.getName() + ",年龄:" + person.getAge());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}}
-
工作原理:
ObjectInputStream会读取字节序列,并根据其中包含的类型信息和成员变量的值,重新构建对象。它会按照序列化时的顺序和规则,将字节序列转换回对象的状态。如果在反序列化过程中遇到类的定义发生变化(如添加或删除成员变量),可能需要特殊的处理来确保对象能够正确地恢复。
相关文章:
Java序列化
Java序列化 简单来说: 序列化是将对象的状态信息转换为可以存储或传输的形式(如字节序列)的过程。在 Java 中,通过序列化可以把一个对象保存到文件、通过网络传输到其他地方或者存储到数据库等。最直接的原因就是某些场景下需要…...
基坑表面位移沉降倾斜自动化监测 非接触式一体化解决机器视觉
基于变焦视觉位移监测仪的基坑自动化监测新方案是一种集成了光学、机械、电子、边缘计算、AI识别以及云平台软件等技术的自动化系统。该方案利用变焦机器视觉原理,结合特殊波段成像识别技术和无源靶标,实现了非接触式大空间、多断面、多测点的高精度水平…...
提升效率:精通Windows命令行的艺术
文章目录 引言1. 基本目录操作命令dir:列出目录内容cd:更改目录mkdir 和 rmdir:创建和删除目录 2. 文件操作命令copy:复制文件或目录move:移动或重命名文件/目录del:删除文件 3. 文件查看命令typeÿ…...
ESP32-S3-devKitC-1 点亮板上的WS2812 RGB LED
ESP32-S3-devKitC-1 板上自带了一个RGB LED,型号为 WS2812。 RGB LED 在板上的位置如下图所示。 为了点亮这个WS2812,需要确定这颗RGB LED连接到哪个GPIO上了。 下面是确定GPIO管脚的过程: 1、根据原理图 2、根据PCB布局图: 程…...
python调用matlab函数(内置 + 自定义) —— 安装matlab.engine
文章目录 一、简介二、安装matlab.engine2.1、基于 CMD 安装2.2、基于 MATLAB 安装(不建议) 三、python调用matlab函数(内置 自定义) 一、简介 matlab.engine(MATLAB Engine API for Python):…...
CAD c# 生成略缩图预览
代码如下: using (Transaction tr currentdb.TransactionManager.StartTransaction()){//当前数据库开启事务using (Database tempdb new Database(false, true)) //创建临时数据库(两个参数:是否创建符号表,不与当前文档关联){try{Bitmap …...
端点鉴别、安全电子邮件、TLS
文章目录 端点鉴别鉴别协议ap 1.0——发送者直接发送一个报文表明身份鉴别协议ap 2.0——ap1.0 的基础上,接收者对报文的来源IP地址进行鉴别鉴别协议ap 3.0——使用秘密口令,口令为鉴别者和被鉴别者之间共享的秘密鉴别协议ap 3.1——对秘密口令进行加密&…...
汽车电子元件的可靠性保障:AEC-Q102认证
AEC-Q102标准的起源与价值 随着汽车电子系统的日益复杂,电子器件必须能够在极端的温度、湿度、振动和电磁干扰等恶劣条件下保持性能。AEC-Q102标准由汽车电子委员会(AEC)制定,专门针对LED、激光二极管和光电二极管等光电器件&…...
主成分分析法大全(包括stata+matlab)
数据简介:主成分分析(Principal Component Analysis,PCA), 是一种统计方法。通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量,转换后的这组变量叫主成分。在实际课题中,为了…...
ubuntu+ros新手笔记(五):初探anaconda+cuda+pytorch
深度学习三件套:初探anacondacudapytorch 系统ubuntu22.04 1.初探anaconda 1.1 安装 安装过程参照【详细】Ubuntu 下安装 Anaconda 1.2 创建和删除环境 创建新环境 conda create -n your_env_name pythonx.x比如我创建了一个名为“py312“的环境 conda cre…...
C++ List(双向链表)
是一个线性链表结构,它的数据由若干个节点构成,每一个节点都包括一个 信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定 的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中&#…...
ASP.NET|日常开发中读写TXT文本详解
ASP.NET|日常开发中读写TXT文本详解 前言一、读取 TXT 文本1.1 使用StreamReader类 二、写入 TXT 文本2.1 使用StreamWriter类 三、文件编码问题3.1 常见编码格式 四、错误处理和性能考虑4.1 错误处理4.2 性能考虑 结束语优质源码分享 ASP.NET|日常开发中…...
【机器学习】在不确定的光影中:机器学习与概率论的心灵共舞
文章目录 概率与统计基础:解锁机器学习的数据洞察之门前言一、概率论基础1.1 概率的基本概念与性质1.1.1 概率的定义1.1.2 样本空间与事件1.1.3 互斥事件与独立事件1.1.4 概率的计算方法 1.2 条件概率与独立性1.2.1 条件概率1.2.2 独立事件 1.3 随机变量1.3.1 随机变…...
【论文笔记】Editing Models with Task Arithmetic
🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: Editing Models with Task…...
ESP32外设学习部分--UART篇
前言 在我们学习嵌入式的过程中,uart算是我们用的非常多的一个外设了,我们可以用串口打印信息,也可以用于设备通信,总之串口的作用非常多,我们也非常有必要熟练地去掌握这个外设。 uart的配置 uart的参数配置 uart_…...
ssm-day04 mybatis
mybatis是一个持久层框架,针对的是JDBC的优化 简化数据库操作,能进行单表、多表操作,在这个框架下,需要我们自己写SQL语句 Mapper接口和MapperXML文件就相当于Dao和Dao层的实现 通常将xml文件放在resources包下 ,放在…...
es中段是怎么合并的
文章目录 1. 段合并的背景2. 合并的方式2.1TieredMergePolicy 的层次结构2.2 层次的基本规则2.3 如何理解层次(tier)2.4. 合并过程中的层次示例2.5. TieredMergePolicy 的优势2.6. 小结 3. 合并过程中的优化4. 合并的性能考虑5. 使用 API 手动合并6. 合并…...
5、可暂停的线程控制模型
一、需求 在做播放器的时候,很多的模块会创建一个线程,然后在这个线程上跑单独的功能,同时,需要对这个线程进行控制,比如暂停,继续等,如播放器的解码,解封装等,都需要对…...
sql优化--mysql隐式转换
sql隐式转换 在SQL中,隐式转换是数据库自动进行的类型转换,隐式转换可以帮助我们处理不同类型的数据。 比如,数据表的字段是字符串类型的,传入一个整型的数据,也能够运行sql。 sql隐式转换的弊端 sql隐式转换&…...
Scratch021(画笔)
画笔模块 可以这么理解,画笔模块是Scratch的拓展模块,用它可以完成很多的功能,非常有趣! 案例要求 点击绿旗运行程序,页面显示需要绘制的背景。 可以使用鼠标移动画笔角色,按照顺序点击连线,…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
