“避免序列化灾难:掌握实现 Serializable 的真相!(二)”

news2024/10/24 0:29:26

文章目录

      • 一、什么是序列化?
      • 二、`Serializable` 是如何起作用的?
      • 三、为什么不自动序列化所有对象?
      • 四、Java 序列化的底层原理
        • 序列化的核心步骤:
      • 五、反序列化的原理
      • 六、总结:为什么必须实现 `Serializable` 才能序列化?
      • 推荐阅读文章

在学习 Java 的时候,你可能遇到过一个疑问: 为什么类必须实现 Serializable,否则就没法序列化对象? 这个看似简单的要求,其实和 Java 的底层机制紧密相关。今天,我们今天就来聊聊这个问题的本质,带你了解为什么 Serializable 是 Java 序列化必不可少的一环。

一、什么是序列化?

先来简单回顾一下什么是序列化。序列化的作用,就是把一个Java 对象转换成字节流,这样我们就可以把它存到文件、通过网络传输、或者传递给其他系统。反过来,把字节流还原成对象的过程叫“反序列化”。

例如,你有一个 User 对象,包含用户名和年龄。序列化后,这个对象会变成一串字节:

User user = new User("Alice", 25);
// 序列化对象到文件
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.ser"));
out.writeObject(user);
out.close();

之后你可以读取文件,反序列化回一个 User 对象:

ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.ser"));
User user = (User) in.readObject();
in.close();

这个过程依赖的是 Java 的序列化机制,而 Serializable 就是这个机制的核心。

二、Serializable 是如何起作用的?

Serializable 是一个标记接口,它本身没有定义任何方法。那它为什么如此重要?让我们从 Java 的序列化机制来看。

Java 序列化机制背后是由 ObjectOutputStreamObjectInputStream 这两个类来完成的。当你调用 writeObject() 方法时,Java 会执行一系列操作来把对象转换为字节流。而这些操作,都是基于对象的类是否实现了 Serializable 接口。如果类没有实现 Serializable,Java 会直接抛出异常,阻止序列化的进行。

为什么会这样呢?这是因为 Java 底层的序列化机制需要知道一个类是否允许被序列化。Serializable 就像是给 Java 的一个“信号”,告诉它这个类的对象是可以被安全地序列化和反序列化的。如果类没有实现 Serializable,Java 默认认为这个类的对象不能被序列化,也就没有办法执行后续操作。

三、为什么不自动序列化所有对象?

你可能会想:为什么 Java 不让所有的类自动支持序列化呢?这样岂不是更方便?

实际上,Java 不自动序列化所有对象,是出于安全性和效率的考虑。原因如下:

  1. 安全性问题
    并不是所有类的对象都适合被序列化。有些类可能包含敏感信息,比如密码、系统配置、用户身份信息等。如果随便把这些类序列化,可能会带来安全隐患。例如,一些类设计时可能没有考虑到数据暴露的问题,而序列化可能会无意间将这些数据泄露给外部系统。

  2. 效率问题
    序列化和反序列化的过程是需要消耗系统资源的,特别是在涉及到复杂对象时。如果 Java 默认让所有类都支持序列化,不仅会增加不必要的开销,还可能导致性能下降。比如某些类可能有非常大的对象图,序列化这些对象可能会产生很大的字节流,影响系统效率。

因此,Java 让开发者自己决定哪些类需要支持序列化,而不是一刀切地自动支持所有类。通过让类实现 Serializable,开发者明确地告诉 Java:这个类是可以被序列化的

四、Java 序列化的底层原理

当一个对象实现了 Serializable 接口,Java 底层会使用反射机制来遍历对象的所有字段,并将这些字段的值按顺序转换成字节流。这其中包括:

  • 基本类型(如 intdouble 等)的直接序列化。
  • 对象类型的递归序列化(比如一个对象里包含另一个对象,也会序列化这个嵌套的对象)。

Java 在序列化时,不仅仅是保存对象的字段值,还会保存一些元信息,包括:

  • 类的名称
  • 类的版本号(serialVersionUID
  • 对象的字段及其类型

这些信息使得在反序列化时,Java 能够找到正确的类,并根据保存的字段值恢复出对象。如果类发生了变化(比如字段修改了),还可以通过 serialVersionUID 来判断序列化和反序列化是否兼容。

序列化的核心步骤:
  1. 判断对象是否实现 Serializable:只有实现了这个接口的对象,才能继续序列化。
  2. 遍历对象的字段:使用反射,Java 会依次获取对象的每个字段,并将其转换成字节流。
  3. 保存对象的元数据:保存类的信息、版本号、以及字段的类型和值。
  4. 生成字节流:最终将这些信息“打包”成字节流,便于存储或传输。

五、反序列化的原理

反序列化的过程则是将字节流重新解析成对象。Java 会根据字节流中的元数据,找到对应的类,并使用反射机制重建对象的实例。这个过程需要类的 serialVersionUID 与字节流中的版本号一致,确保类结构没有发生不兼容的变化。

如果对象的类没有实现 Serializable,反序列化时也会失败,因为 Java 没有办法恢复出一个未标记为可序列化的类的对象。

六、总结:为什么必须实现 Serializable 才能序列化?

  • Serializable 是一个标记,告诉 Java 这个类可以安全地被序列化和反序列化。Java 需要这个信号来决定是否执行序列化操作。
  • 安全性:并不是所有对象都适合被序列化,Serializable 让开发者有选择地开放序列化权限,避免敏感数据泄露。
  • 效率:序列化和反序列化是有成本的,不自动支持所有类序列化可以避免不必要的性能开销。
  • 底层机制:Java 使用 Serializable 接口配合反射来实现序列化和反序列化过程,只有实现了 Serializable 的类,Java 才会执行序列化流程。

因此,Java 之所以要求类实现 Serializable,是为了通过这一标记来确保序列化的安全性、性能,以及在底层能够正确执行序列化过程。这也是为什么我们必须显式地让类实现 Serializable,否则 Java 序列化机制就没法发挥作用。

推荐阅读文章

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程
  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
  • 如何理解应用 Java 多线程与并发编程?
  • Java Spring 中常用的 @PostConstruct 注解使用总结
  • 线程 vs 虚拟线程:深入理解及区别
  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
  • Java 中消除 If-else 技巧总结
  • 线程池的核心参数配置(仅供参考)
  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)
  • Java 枚举的几个常用技巧,你可以试着用用
  • 如何理解线程安全这个概念?
  • 理解 Java 桥接方法
  • Spring 整合嵌入式 Tomcat 容器
  • Tomcat 如何加载 SpringMVC 组件

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

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

相关文章

Java | Leetcode Java题解之第492题构造矩形

题目: 题解: class Solution {public int[] constructRectangle(int area) {int w (int) Math.sqrt(area);while (area % w ! 0) {--w;}return new int[]{area / w, w};} }

自定义多级联动选择器指南(uni-app)

多端支持:可以运行在H5、APP、微信小程序还是支付宝小程序,都可以轻松使用改组件。自定义配置:您可以根据需要配置选择器的级数,使其适应不同的数据结构和用例。无限级联:此组件支持无限级联选择,使您能够创…

MySQL8.0主从同步报ERROR 13121错误解决方法

由于平台虚拟机宿主机迁移,导致一套MySQL主从库从节点故障,从节点服务终止,在服务启动后,恢复从节点同步服务,发现了如下报错: mysql> show slave status\G; *************************** 1. row *****…

整合全文检索引擎 Lucene 添加站内搜索子模块

整合全文检索引擎 Lucene: 添加站内搜索子模块 1. 什么是 Lucene ? 有啥优势? Lucene 是一个开源的全文检索引擎库,由 Apache 基金会维护,官网地址:https://lucene.apache.org/ 。它提供了丰富的文本处理和搜索功能&#xff0c…

IO、存储、硬盘:解析文件系统和File类

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! 在计算机科学中,IO(输入/输出)、存储、硬盘和文件系统是构成计算机数据处理和存储的基础。本文将探讨这些概念,特别是文件系统的工作原理和相关知识。 输入/输出…

【C++篇】探索STL之美:熟悉使用String类

CSDN 文章目录 前言 💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力! 👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗&…

吴恩达深度学习笔记(8)

计算机视觉 包括:图像分类也叫做图像识别、目标检测等 一个小的图像可能1M,但是他的像素是一个超级大向量,如果直接深度学习那么运算量会很大,因此需要运用卷积运算。 卷积运算是卷积神经网络的基础单元之一。下面用边缘检测理…

【Qt】控件——Qt多元素控件、常见的多元素控件、多元素控件的使用、List Widget、Table Widget、Tree Widget

文章目录 QtQt多元素控件List WidgetTable WidgetTree Widget Qt Qt多元素控件 List Widget 使用 QListWidget 能够显示一个纵向的列表。 属性说明currentRow当前被选中的是第几行。count一共有多少行。sortingEnabled是否允许排序。isWrapping是否允许换行。itemAlignment元素…

软件架构的 “4+1” 视图(附视图案例)

简介 Philippe Kruchten 在《IEEE Software》上发表的《The 41 View Model of Architecture》论文中提出了“41”视图方法,该方法被RUP采纳。“41”视图模型通过逻辑视图、进程视图(也称为处理视图)、物理视图、开发视图 和 场景视图 五个视…

YOLOv9改进,YOLOv9引入FLAttention注意力机制(ICCV2023),并二次创新RepNCSPELAN4结构

摘要 自我注意的二次计算复杂度在将 Transformer 模型应用于视觉任务时,这是一个长期存在的问题。除了减少注意力区域外,线性注意力也被认为是避免过多计算成本的有效解决方案。通过使用精心设计的映射函数来逼近 Softmax,线性注意力可以在自注意力操作中切换计算顺序并实现…

HTTP Proxy环境下部署Microsoft Entra Connect和Health Agents

在企业环境中,时常需要通过使用HTTP Proxy访问Internet,在使用HTTP Proxy访问Internet的环境中部署Microsoft Entra Connect和Microsoft Entra Connect Health Agents可能会遇到一些额外的配置步骤,以便这些服务能够正常连接到Internet。 一…

再Android10上实现检测AHD摄像头是否接入

项目有个需要,需要知道tp9951是否接入AHD摄像头 1,驱动层可以通过读取寄存器的值来检测是否接入AHD摄像头 tp9951_write_reg(0x40, 0x00); //select decoder page tp9951_write_reg(0x41, ch); val tp9951_read_reg(TP_INPUT_STATUS_REG);…

vscode默认添加python项目的源目录路径到执行环境(解决ModuleNotFoundError: No module named问题)

0. 问题描述 vscode中编写python脚本,导入工程目录下的其他模块,出现ModuleNotFoundError: No module named 错误 在test2的ccc.py文件中执行print(sys.path) 查看路径 返回结果发现并无’/home/xxx/first_demo’的路径,所以test2下面的文…

Vscode + EIDE +CortexDebug 调试Stm32(记录)

{// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid830387"version": "0.2.0","configurations": [{"cwd": "${workspaceRoot…

w~自动驾驶合集9

我自己的原文哦~ https://blog.51cto.com/whaosoft/12320882 #自动驾驶数据集全面调研 自动驾驶技术在硬件和深度学习方法的最新进展中迅速发展,并展现出令人期待的性能。高质量的数据集对于开发可靠的自动驾驶算法至关重要。先前的数据集调研试图回顾这些数据集&…

Djang学习- URL反转

代码中url书写规范&#xff1a; 、 url反向解析 urls: path(test/url, views.test_url),path(test_result/<int:age>, views.test_result, name"rl") views: def test_url(request):return render(request, test_url.html)def test_result(request,age):re…

Vue3学习:vite项目中图片不能显示,报错 require is not defined

今天做了一个案例“给你喜欢的人送花”&#xff0c;如果喜欢谁&#xff0c;就给谁送花&#xff0c;最多可以送5朵。运行效果如下。 这个项目是使用 npm create vitelatest 命令创建的。 包括2个组件&#xff1a; 根组件App.vue子组件HelloVote.vue。 目录结构如图所示&#x…

资讯 | 财富通科技政务协同办公管理软件通过麒麟软件适配认证

2024年9月25日&#xff0c;财富通科技研发的政务协同办公管理软件成功通过中国国产操作系统麒麟软件的适配认证。本次认证是继公司区块链产品“基于区块链的企业及人员资质数字证书服务平台”认证以后得第二次认证。这一成就标志着财富通科技在推动国产软件生态建设方面迈出了坚…

基于SSM+微信小程序的家庭记账本管理系统(家庭1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 1、管理员端功能有首页、个人中心、用户管理&#xff0c;消费详情管理、收入详情管理、系统管理等。 2、用户端功能有首页、消费详情、收入详情、论坛信息、我的等功能。 2、项目技术 …

数据结构作业day2

作业一&#xff1a;结构体数组存储学生信息&#xff08;姓名&#xff0c;年龄&#xff0c;分数&#xff09;&#xff0c;完成输入学生信息&#xff0c;输出学生信息&#xff0c;求学生成绩之和&#xff0c;求最低学生成绩。 main.c #include "test.h"int main(int …