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的拓展模块,用它可以完成很多的功能,非常有趣! 案例要求 点击绿旗运行程序,页面显示需要绘制的背景。 可以使用鼠标移动画笔角色,按照顺序点击连线,…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
