Java中的序列化和反序列化:深入理解和实战

文章目录

      • 1. 简介
      • 2. Java中的序列化
      • 3. Java中的反序列化
      • 4. Java序列化中的常见问题和解决策略
      • 5. 自定义序列化
      • 6. 常见问题及解答
      • 7. 使用场景
      • 8. 结尾

1. 简介

序列化和反序列化的本质是解决在进行远程通信和持久化数据时,如何保存和恢复数据的问题。

  • ** 序列化:** 将数据结构或对象转换成二进制字节流的过程
  • ** 反序列化: ** 将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程

为什么要进行序列化和反序列化操作?
其实主要是为了持久化和进行传输,我们都知道在Java 中一些数据都是以对象的形式存在的,那如果我想把对象传输其他人怎么办?

那肯定是不能直接传输的,假如我们要进行网络传输,传输的过程中是不能传输Java 对象的,因为底层的实现并不知道Java 对象的存在,我们一般都是传输字节,所以我们需要能够进行传输的形式,序列化就是这个操作,我们将Java 对象序列化为一个字节数组,这样就可以进行传输了。

这个原理不仅在Java中,在所有需要进行远程通信和数据存储的编程语言中都存在。

2. Java中的序列化

为了在Java中实现序列化,我们需要完成以下两个步骤。

首先,让我们要序列化的类实现Serializable接口。下面是一个实现了Serializable接口的Person类。

public class Person implements Serializable {private String name;// getter 和 setter 方法省略
}

然后,我们可以使用java.io.ObjectOutputStream类将Person对象写入到硬盘中,如下所示:

Person person = new Person();
person.setName("Grace");try (FileOutputStream fos = new FileOutputStream("person.obj");ObjectOutputStream oos = new ObjectOutputStream(fos)) {oos.writeObject(person);
} catch (IOException e) {e.printStackTrace();
}

3. Java中的反序列化

反序列化就是将序列化的字节流恢复成原来的对象。我们可以通过java.io.ObjectInputStream类来完成这个过程,如下所示:

try (FileInputStream fis = new FileInputStream("person.obj");ObjectInputStream ois = new ObjectInputStream(fis)) {Person person = (Person) ois.readObject();System.out.println(person.getName());
} catch (IOException | ClassNotFoundException e) {e.printStackTrace();
}

4. Java序列化中的常见问题和解决策略

序列化并不总是那么简单。我们可能会遇到版本控制问题、子类序列化,以及某些字段不应该被序列化的问题。

  • 版本控制问题: 在序列化对象中,serialVersionUID是JAVA为了有效地实现序列化所引入的。serialVersionUID作为版本控制,在反序列化过程中,JAVA虚拟机会根据版本号确保序列化类的一致性。如果对象的版本号不一致,反序列化过程就会失败,抛出InvalidClassException异常。示例:

    public class Person implements Serializable {private static final long serialVersionUID = 1L;// 其他代码省略
    }
    
  • 子类序列化: 在Java中,父类通过实现Serializable接口,子类可以由此自动实现序列化,反之则不行。当子类需要序列化,而父类并未实现序列化接口时,可以通过在子类添加一个父类的构造器来解决。这样的示例:

    public class Person {private String name;Person(String name){this.name = name;// 其他代码省略}
    }public class Employee extends Person implements Serializable {private int employeeId;Employee(String name, int employeeId) {super(name);this.employeeId = employeeId;// 其他代码省略}
    }
    
  • transient关键字: 在序列化过程中,可能某些字段并不需要序列化,比如说一些敏感信息(如密码、银行卡号等)。这时可以使用transient关键字标记不需要序列化的字段。值得注意的是,被transient关键字标记的字段,在反序列化回来后将为null。示例:

    public class Person implements Serializable {private String name;private transient String password; // 此字段不会被序列化// getter 和 setter 方法省略
    }
    

5. 自定义序列化

有时候,我们可能想要更多地控制序列化的过程。Java为我们提供了自定义序列化的方法——通过在我们的类中重写writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in)方法,我们就可以控制对象的序列化过程。示例:

public class Person implements Serializable {private String name;private transient String password; // 此字段不会被序列化private void writeObject(ObjectOutputStream out) throws IOException {out.defaultWriteObject();out.writeObject(password); }private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();password = (String) in.readObject(); }// getter 和 setter 方法省略
}

6. 常见问题及解答

  • 没有实现Serializable接口的类的对象能否序列化? 不可以。如果对象的类没有实现 Serializable 接口,那么将无法通过ObjectOutputStream进行序列化。
  • 静态变量参与序列化吗? 不参与。因为static的变量属于类级别的,序列化只处理对象的状态,即类的非静态字段。静态变量的生命周期和对象不同,由JVM负责维护。
  • 如何控制是否序列化字段? 对于不需要序列化的字段,我们可以使用transient关键字。被transient修饰的字段在序列化时将被忽略,反序列化时按照字段类型的默认值填充。
  • 如何保证序列化对象的安全性? 对于需要序列化的敏感信息对象,我们可以在序列化时加密,反序列化时解密来保证安全性。另外,选择可靠的存储和传输方式也是重要的安全保障。

7. 使用场景

序列化被广泛应用于各种场景,如远程调用(RMI或EJB),持久化(Hibernate),HTTP会话在集群节点间的复制等。理解序列化及反序列化的原理和实现,对掌握Java及各种Java框架和中间件至关重要。

下面是序列化和反序列化常见应用场景:

  • 对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
  • 将对象存储到文件之前需要进行序列化,将对象从文件中读取出来需要进行反序列化;
  • 将对象存储到数据库(如 Redis)之前需要用到序列化,将对象从缓存数据库中读取出来需要反序列化;
  • 将对象存储到内存之前需要进行序列化,从内存中读取出来之后需要进行反序列化。

8. 结尾

序列化和反序列化看似简单的概念,但实则包含了许多复杂的细节。希望通过这篇文章,能够帮助大家更深入地理解序列化和反序列化的过程,以及如何在实际编程中使用序列化。

如文章有任何疑问,欢迎提出!
欢迎大家访问我的个人博客 无限进步的博客

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

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

相关文章

stm32学习笔记:TIIM-输入捕获

输入捕获理论 4个输入捕获和输出比较通道,共用4个CCR寄存器 另外它们的CH1到CH4,4个通道的引脚,也是共用的。 所以对于同一个定时器,输入捕获和输出比较只能使用其中一个,不能同时使用。 电平跳变:上升沿…

《动手学深度学习》学习笔记 第5章 深度学习计算

本系列为《动手学深度学习》学习笔记 书籍链接:动手学深度学习 笔记是从第四章开始,前面三章为基础知道,有需要的可以自己去看看 关于本系列笔记: 书里为了让读者更好的理解,有大篇幅的描述性的文字,内容很…

Spring学习 Spring概述

1.1.Spring介绍 ​ Spring是轻量级Java EE应用开源框架(官网: http://spring.io/ ),它由Rod Johnson创为了解决企业级编程开发的复杂性而创建 1.2.简化应用开发体现在哪些方面? IOC 解决传统Web开发中硬编码所造成的…

python中collections.abc.Mapping 和collections.Mapping的区别

文章目录 在 Python 中,collections.abc.Mapping 和 collections.Mapping 都是用于表示映射类型(即键值对的集合,例如字典)的抽象基类。它们的区别在于它们的来源和使用方式。 collections.abc.Mapping 是 collections.abc 模块中…

1月5日代码随想录完全二叉树的节点个数

222.完全二叉树的节点个数 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在…

使用ModelScope运行或者微调模型ModelScope国内一个“模型即服务”(MaaS)平台

TOC 一、ModelScope社区 ModelScope是一个“模型即服务”(MaaS)平台,由阿里推出维护,旨在汇集来自AI社区的最先进的机器学习模型,并简化在实际应用中使用AI模型的流程。ModelScope库使开发人员能够通过丰富的API设计执行推理、训练和评估&a…

即时设计:轻松实现设计稿动画,打造独具魅力的GIF作品

制作动画 随着动画设计越来越受欢迎,设计师们需要一款强大的工具,以便轻松控制设计稿元素的属性,实现动画效果。今天,我们向您推荐一款具备帧动画功能的设计工具,它可以让您轻松调整元素的宽高、相对位置等属性&#x…

Spring AI 指南

近年来,人工智能技术的迅猛发展改变了我们对科技的看法,并在各个领域引发了巨大的变革。每个人都希望在自己的项目上能够使用人工智能。Spring 框架提供了一个名为 “Spring AI” 的项目,Spring AI 项目旨在简化包含人工智能功能的应用程序的…

Python 基础面试第四弹

1. Python中常用的库有哪些,作用分别是什么 requests: requests 是一个用于发送 HTTP 请求的库,它提供了简单而优雅的 API,可以轻松地发送 GET、POST、PUT、DELETE 等请求,并处理响应数据。它支持会话管理、身份验证、文件上传等常…

Matlab绘制动态心形线

1. 代码 for alpha0:0.1:30 x-1.8:0.001:1.8; y(x.^2).^(1/3)0.9*(3.3-x.^2).^(1/2).*sin(alpha*pi*x); plot(x,y,r-,LineWidth,1.2); set(gca,YGrid,on); axis([-3,3,-2,4]); text(-2,3.35,$f(x)x^{\frac{2}{3}}0.9(3.3-x^2)^{\frac{1}{2}}sin(\alpha\pi x)$,Interpreter,lat…

Geotrust DV通配符证书保护域名数量

Geotrust是一家知名的SSL证书提供商,旗下有多种类型的SSL数字证书,保护网站数据在传输过程中的安全性和完整性,帮助用户确认其网站的安全。通配符SSL证书是Geotrust颁发的一种可以同时保护多个域名站点的SSL证书。今天就随SSL盾小编了解Geotr…

Toshiba 数字隔离器助力工业应用实现稳定的高速隔离数据传输

隔离器件是将输入信号进行转换并输出,以实现输入、输出两端电气隔离的一种安规器件。电气隔离能够保证强电电路和弱电电路之间信号传输的安全性,如果没有进行电气隔离,一旦发生故障,强电电路的电流将直接流到弱电电路,…

啊哈c语言——逻辑挑战8:验证哥德巴赫猜想

上面这封书信是普鲁士数学家哥德巴赫在1742年6月7日写给瑞士数学家欧拉的,哥德巴赫在书信中提出了“任一大于2的整数都可以写成3个质数之和”的猜想。当时,哥德巴赫遵照的是“1也是素数”的约定。现今,数学界已经不使用这个约定了。哥德巴赫原…

Spring Boot 整合 Knife4j(快速上手)

关于 Knife4j 官方文档:https://doc.xiaominfo.com/ Knife4j是一个基于Swagger的API文档生成工具,它提供了一种方便的方式来为Spring Boot项目生成在线API文档。Knife4j的特点包括: 自动化生成:通过Swagger注解,Kn…

yq操作yaml插入列表数据支持传参

yq是基于golang语言开发的一款json、yaml以及xml命令行工具,支持多个平台,github官网:GitHub - mikefarah/yq: yq is a portable command-line YAML, JSON, XML, CSV, TOML and properties processor 文档地址:Shell Completion …

凸优化 3:最优化方法

凸优化 3:最优化方法 最优化方法适用场景对比费马引理一阶优化算法梯度下降最速下降 二阶优化算法牛顿法Hessian矩阵Hessian矩阵的逆Hessian矩阵和梯度的区别牛顿法和梯度下降法的区别 拟牛顿法DFP、BFGS/L-BFGS 数值优化算法坐标下降法SMO算法 基于导数的函数优化解…

应用程序支持的系统版本

在使用 Android Studio 创建 Android 项目时,Minimum SDK 选项表示应用程序所需的最低 Android API 级别。这个选项让您指定应用程序可以运行的最小 Android 版本。 在构建应用程序时,您可能需要使用一些最新的 Android API 来实现某些功能。但是&#x…

FCN学习-----第一课

语义分割中的全卷积网络 CVPR IEEE国际计算机视觉与模式识别会议 PAMI IEEE模式分析与机器智能汇刊 需要会的知识点: 神经网络:前向传播和反向传播 卷积神经网络:CNN,卷积,池化,上采样 分类网络&#xff1a…

杨中科 ASP.NETCore Rest

什么是Rest RPC 1、Web API两种风格: 面向过程(RPC) 、面向REST (REST) 2、RPC:“控制器/操作方法“的形式把服务器端的代码当成方法去调用。把HTTP当成传输数据的通道,不关心HTTP谓词。通过QueryString请求报文体给服务器传递数据。状态码。比如/Persons/GetAll…

紧跟国际潮流,勇探未知领域

紧跟国际潮流,勇探未知领域 文章目录 紧跟国际潮流,勇探未知领域一、计算产业新面貌二、紧跟AI新潮流1、我国人工智能产业发展表现出明显的集群化趋势2、人工智能产业集群是基于网络空间发展的创新集群三、企业簇群及其产业创新生态四、创新的“极化”和…