Java序列化与反序列化深度解析

一、引言


在 Java 开发中,序列化与反序列化是非常重要的概念和技术手段。它允许我们将对象转换为字节流以便于存储或传输,然后在需要的时候再将字节流还原为对象。这一机制在很多场景中都有着广泛的应用,例如数据持久化、分布式系统中的远程方法调用(RMI)、缓存等。本文将深入探讨 Java 序列化与反序列化的原理、实现方式以及相关的注意事项和最佳实践。

二、什么是 Java 序列化与反序列化

  1. 序列化
    序列化是将对象的状态信息转换为可以存储或传输的形式(通常是字节流)的过程。在 Java 中,一个对象要能够被序列化,其所属的类必须实现 java.io.Serializable 接口。这个接口是一个标记接口,没有任何方法定义,仅仅用于标识该类的对象可以被序列化。当序列化一个对象时,Java 会将对象的非静态和非瞬态成员变量的值转换为字节流。
  2. 反序列化
    反序列化则是与序列化相反的过程,即将字节流转换回对象的过程。通过反序列化,可以从存储介质(如文件)或网络传输中读取字节流,并将其还原为原始的对象状态,使得程序可以继续对对象进行操作。

三、Java 序列化与反序列化的实现

  1. 基本序列化与反序列化示例
    以下是一个简单的 Java 类实现序列化与反序列化的示例代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;class Person implements Serializable {private static final long serialVersionUID = 1L;private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}// Getters and setters (omitted for brevity)@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class SerializationDemo {public static void main(String[] args) {// SerializationPerson person = new Person("John", 30);try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {oos.writeObject(person);System.out.println("Object serialized successfully.");} catch (IOException e) {e.printStackTrace();}// Deserializationtry (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {Person deserializedPerson = (Person) ois.readObject();System.out.println("Deserialized object: " + deserializedPerson);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

在上述代码中,Person 类实现了 Serializable 接口,从而具备了可序列化的能力。在 main 方法中,首先创建了一个 Person 对象并进行序列化,将其保存到名为 person.ser 的文件中。然后通过反序列化从文件中读取字节流并还原为 Person 对象并打印出来。

  1. serialVersionUID 的作用
    serialVersionUID 是一个用于版本控制的长整型常量。在序列化和反序列化过程中,它用于验证序列化对象和反序列化时的类是否兼容。如果在序列化后类的结构发生了变化(如添加、删除或修改成员变量),而没有正确更新 serialVersionUID,可能会导致反序列化失败并抛出 InvalidClassException 异常。当类的结构没有变化时,应该保持 serialVersionUID 的一致性;当类的结构发生变化且希望保持向后兼容性时,需要根据变化情况合理地更新 serialVersionUID

四、序列化与反序列化的应用场景

  1. 数据持久化
    将对象序列化后存储到文件系统或数据库中,可以方便地保存对象的状态信息。例如,在保存游戏进度时,可以将游戏中的角色、道具等对象序列化后保存到本地文件,下次启动游戏时再反序列化恢复游戏状态。
  2. 分布式系统通信
    在分布式系统中,不同节点之间可能需要传输对象数据。通过序列化将对象转换为字节流,可以在网络上进行传输,接收方再进行反序列化得到原始对象,从而实现远程方法调用(RMI)等分布式通信功能。
  3. 缓存机制
    缓存系统中常常需要存储各种对象数据以便快速访问。将对象序列化后存储到缓存中(如 Redis 等缓存数据库),可以提高数据的读取速度并减少对底层数据源的频繁访问压力。

五、序列化与反序列化的注意事项与最佳实践

  1. 安全性考虑
    序列化可能会带来安全风险,因为恶意攻击者可以构造恶意的字节流来进行反序列化攻击,例如导致代码执行、信息泄露等。为了提高安全性,尽量避免对不信任的数据源进行反序列化操作。可以使用一些安全框架如 Java 自带的安全管理器或第三方库(如 SerialKiller 等)来限制反序列化的范围和权限。
  2. 性能优化
    • 对于大规模数据的序列化与反序列化,要考虑性能影响。可以选择高效的序列化库,如 Kryo、Protobuf 等,它们在某些场景下比 Java 原生的序列化性能更好。
    • 避免过度序列化不必要的数据。只序列化真正需要存储或传输的对象成员变量,减少数据量和序列化时间。
  3. 对象图处理
    当对象之间存在复杂的关联关系形成对象图时,在序列化时要注意避免循环引用导致的栈溢出等问题。可以通过合理设计对象结构或使用特定的序列化库来处理循环引用情况。

六、总结


Java 序列化与反序列化是强大而重要的技术手段,它为数据的存储、传输和交互提供了便利。通过深入理解其原理、正确实现序列化与反序列化过程,并遵循相关的注意事项和最佳实践,我们可以在 Java 开发中更好地利用这一技术来构建高效、安全和可靠的应用程序,无论是在本地数据处理还是分布式系统开发等领域都能发挥其关键作用。同时,随着技术的发展,也不断有新的序列化库和技术出现,开发者可以根据具体需求选择合适的工具来优化序列化与反序列化的性能和功能。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习—建立表现基准

让我们来看看一些具体的数字,Jtrain和Jcv是什么,以及如何做出判断,如果学习算法具有高偏差或高方差,使用一个语音识别应用的例子作为讲解。 很多在手机上进行网络搜索的用户会使用语音识别,而不是在手机上的小键盘上打…

阮一峰科技爱好者周刊(第 325 期)推荐工具:一个基于 Next.js 的博客和 CMS 系统

近期,阮一峰在科技爱好者周刊第 325 期中推荐了一款开源工具——ReactPress,ReactPress一个基于 Next.js 的博客和 CMS 系统,可查看 demo站点。(fecommunity 投稿) ReactPress:一款值得推荐的开源发布平台 …

大学语文教材电子版(第十一版)教学用书PDF及课件

大学语文课件:https://caiyun.139.com/m/i?005CiDusEVWnR 《大学语文》(第十一版)主编:徐中玉 齐森华 谭帆。 大学语文教材电子版教师用书PDF第一课《齐桓晋文之事》艺术赏析: 孟子四处游说,养成善辩的…

RK356x-8:Wifi模块AP6xxx配置与调试

本文记录如何根据原理图,配置和调试RK356x(测试用RK3566)主板上wifi/蓝牙模块(测试用AP6212,rkwifibt),使其能正确连网。 1.配置SOC接口 1.1 查看原理图,看看wifi模块用的接口是什…

Java基础——网络编程

可以让设备中的程序与网络上其他设备中的程序进行数据交互(实现网络通信的)。 1. 基本的通信架构 基本的通信架构有2种形式:CS架构(Client客户端/Server服务端)、BS架构(Browser浏览器/Server服务端&…

变分自编码器(VAE, Variational Autoencoder)

代码说明 VAE 模型结构: 编码器将输入数据(如 MNIST 图像)映射到潜在空间,生成均值 (mu) 和对数方差 (logvar)。 通过重新参数化技巧 (reparameterize) 从正态分布中采样潜在向量 z。 解码器将潜在向量 z 映射回原始空间&#xf…

1. Django中的URL调度器 (项目创建与简单测试)

1. 创建 Django 项目 运行以下命令创建一个名为 blog_project 的 Django 项目: django-admin startproject blog_project2. 创建博客应用 Django 中,项目可以包含多个应用。创建一个名为 blog 的应用: cd blog_project python manage.py …

多目标优化算法:多目标黑翅鸢算法(MOBKA)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码

一、黑翅鸢算法介绍 黑翅鸢优化算法(Black-winged Kite Algorithm, BKA)是2024年提出的一种元启发式优化算法,其灵感来源于黑翅鸢的迁徙和捕食行为。这种算法通过模拟黑翅鸢在捕食过程中的飞行和搜索策略,被用来解决优化问题&…

记一次Mysql远程连接报错

问题描述: Plugin caching sha2 password could not be loaded: 在wsl2用docker中拉取了mysql镜像,启动后想在win下的环境远程连接到docker中的mysql,报错了,报错如下所示 搜寻了相关的资料发现,在拉下来的myslq版本…

STM32F103移植FreeRTOS

1. 源码下载 在https://www.freertos.org/中下载源码,这里下载的是FreeRTOSv202212.01版本,源码内容解释可参考: https://rtos.100ask.net/zh/FreeRTOS/DShanMCU-F103/chapter7.html#_7-1-freertos%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84拷贝…

CAD多段线两侧偏移(交叉线容易出错)

public void 交叉多段线容易出错(){List<Curve> entse Z.db.SelectEntities<Curve>();List<Polyline> ents Z.db.CurvesToPolyLines(entse);//Z.db.SelectEntities<Polyline>();double offsetDistance 5.0;//偏移距离List<Polyline> resultP…

数据库EVA模式与传统数据库模式 | 分析对比及应用场景

目录 1. 实战场景2. 基本知识3. 应用场景 1. 实战场景 从实战进行探讨以及深入&#xff1a; 事因是同事给我创建表结构的时候&#xff0c;以如下这种方式进行创建&#xff1a; 看到这张表的结构可能会思考&#xff1a; 为啥设备的部件值&#xff08;日期、数值、字符串&…

算法【Java】—— 动态规划之简单多状态 dp 问题

按摩师 https://leetcode.cn/problems/the-masseuse-lcci 状态表示&#xff1a;根据经验和题目要求&#xff0c;达到 i 位置的时候&#xff0c;预约时间最长 接着我们细分状态表示&#xff1a;在遍历数组的时候&#xff0c;到达 i 位置的时候&#xff0c;又两种情况&#xff…

小鸡模拟器 1.8.11 | 街机怀旧重温经典游戏,支持手柄

小鸡模拟器是一款支持多种经典游戏机模拟的游戏应用&#xff0c;包括街机、索尼(SONY)、世嘉、任天堂等主流掌机游戏以及PSP、GBA、NDS、SFC(超级任天堂SNES)、FC(红白机NES)、MD(世嘉MEGA DRIVE)、PS1、PS2等。应用支持手柄完美操作&#xff0c;兼容安卓手柄&#xff0c;让玩家…

Pygame坦克大战游戏开发实验报告

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Springboot3.3.5 启动流程之 tomcat启动流程介绍

在文章 Springboot3.3.5 启动流程&#xff08;源码分析&#xff09; 中讲到 应用上下文&#xff08;applicationContext&#xff09;刷新(refresh)时使用模板方法 onRefresh 创建了 Web Server. 本文将详细介绍 ServletWebServer — Embedded tomcat 的启动流程。 首先&…

电子应用设计方案-12:智能窗帘系统方案设计

一、系统概述 本设计方案旨在打造便捷、高效的全自动智能窗帘系统。 二、硬件选择 1. 电机&#xff1a;选用低噪音、扭矩合适的智能电机&#xff0c;根据窗帘尺寸和重量确定电机功率&#xff0c;确保能平稳拉动窗帘。 2. 轨道&#xff1a;选择坚固、顺滑的铝合金轨道&…

Javaweb-day12(登录认证)

登录功能 登录校验&#xff08;重点&#xff09; 登录校验指的是在服务器接收到浏览器发送过来的请求之后&#xff0c;首先要对这个请求进行校验&#xff0c;先要校验一下用户登录了没有 怎么来实现登录校验的操作呢&#xff1f;具体的实现思路可以分为两部分&#xff1a; 在…

记录大学Linux运维上机考试题目和流程

备注&#xff1a;今年的Linux操作系统考试已经全部结束&#xff0c;仅作为一个记录和留念 前提&#xff1a;配置环回网卡和环境和nat网卡 1、搭建dns服务器 2、Apache和http服务 3、搭建postfix邮件服务器实现邮件发送 4、搭建vsftpdFTP服务器实现文件上传 题目如下&…

Linux驱动开发第2步_“物理内存”和“虚拟内存”的映射

“新字符设备的GPIO驱动”和“设备树下的GPIO驱动”都要用到寄存器地址&#xff0c;使用“物理内存”和“虚拟内存”映射时&#xff0c;非常不方便&#xff0c;而pinctrl和gpio子系统的GPIO驱动&#xff0c;非常简化。因此&#xff0c;要重点学习pinctrl和gpio子系统下的GPIO驱…