0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

实现序列化和反序列化为什么要实现Serializable接口

Android编程精选 来源:CSDN 作者:椰子Tyshawn 2022-07-12 11:05 次阅读

做服务化,需要把所有model包里的类都实现Serializable接口, 同时还要显示指定serialVersionUID的值。听到这个需求,我脑海里就突然出现了好几个问题,比如说:

序列化和反序列化

序列化:把对象转换为字节序列的过程称为对象的序列化。

反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

什么时候需要用到序列化和反序列化呢?

当我们只在本地JVM里运行下Java实例,这个时候是不需要什么序列化和反序列化的, 但当我们需要将内存中的对象持久化到磁盘, 数据库中时,当我们需要与浏览器进行交互时, 当我们需要实现RPC时,这个时候就需要序列化和反序列化了。

前两个需要用到序列化和反序列化的场景,是不是让我们有一个很大的疑问? 我们在与浏览器交互时,还有将内存中的对象持久化到数据库中时,好像都没有去进行序列化和反序列化,因为我们都没有实现Serializable接口, 但一直正常运行。

下面先给出结论:

只要我们对内存中的对象进行持久化或网络传输, 这个时候都需要序列化和反序列化.

理由:

服务器与浏览器交互时真的没有用到Serializable接口吗? JSON格式实际上就是将一个对象转化为字符串, 所以服务器与浏览器交互时的数据格式其实是字符串, 我们来看来String类型的源码:

poYBAGLM5WaAeyVsAADlsXQGlkM013.jpg

String类型实现了Serializable接口,并显示指定serialVersionUID的值。

然后我们再来看对象持久化到数据库中时的情况,Mybatis数据库映射文件里的insert代码:

pYYBAGLM5X6AeU3SAABSix10Bbk078.jpg

实际上我们并不是将整个对象持久化到数据库中, 而是将对象中的属性持久化到数据库中, 而这些属性都是实现了Serializable接口的基本属性。

实现序列化和反序列化为什么要实现Serializable接口?

在Java中实现了Serializable接口后,JVM会在底层帮我们实现序列化和反序列化, 如果我们不实现Serializable接口, 那自己去写一套序列化和反序列化代码也行, 至于具体怎么写, Google一下你就知道了。

实现Serializable接口就算了, 为什么还要显示指定serialVersionUID的值?

如果不显示指定serialVersionUID,JVM在序列化时会根据属性自动生成一个serialVersionUID, 然后与属性一起序列化,再进行持久化或网络传输. 在反序列化时,JVM会再根据属性自动生成一个新版serialVersionUID,然后将这个新版serialVersionUID与序列化时生成的旧版serialVersionUID进行比较, 如果相同则反序列化成功, 否则报错.

如果显示指定了serialVersionUID, JVM在序列化和反序列化时仍然都会生成一个serialVersionUID, 但值为我们显示指定的值, 这样在反序列化时新旧版本的serialVersionUID就一致了。

在实际开发中, 不显示指定serialVersionUID的情况会导致什么问题? 如果我们的类写完后不再修改, 那当然不会有问题, 但这在实际开发中是不可能的,我们的类会不断迭代, 一旦类被修改了,那旧对象反序列化就会报错. 所以在实际开发中, 我们都会显示指定一个serialVersionUID, 值是多少无所谓, 只要不变就行。

写个实例测试下:

User类

不显示指定serialVersionUID.

poYBAGLM5bmATDjoAADE3tBVFuI262.jpg

poYBAGLM5cKARs6HAABKja56wSg415.jpg

测试类

先进行序列化, 再进行反序列化.

pYYBAGLM5fGADpVAAAGAgrSz_mw962.jpg

pYYBAGLM5fmAEUlsAAA8Wgz1H6o479.jpg

结果

先注释掉反序列化代码,执行序列化代码,然后User类新增一个属性sex。

pYYBAGLM5iWAZJxyAADVZJJr1Bw657.jpg

pYYBAGLM5i2ACbSAAACcP1Hf3Dg941.jpg

再注释掉序列化代码执行反序列化代码,最后结果如下:

序列化前的结果: User{name='tyshawn', age=18}Exception in thread "main" java.io.InvalidClassException: org.tyshawn.SerializeAndDeserialize.User; local class incompatible: stream classdesc serialVersionUID = 1035612825366363028, local class serialVersionUID = -1830850955895931978报错结果为序列化与反序列化产生的serialVersionUID不一致。

接下来我们在上面User类的基础上显示指定一个serialVersionUID。

poYBAGLM5lmALd2xAAAeVtahAXk183.jpg

再执行上述步骤, 测试结果如下:

poYBAGLM5miAFVtCAABGruQrwYg110.jpg

显示指定serialVersionUID后就解决了序列化与反序列化产生的serialVersionUID不一致的问题。

Java序列化的其他特性

先说结论, 被transient关键字修饰的属性不会被序列化, static属性也不会被序列化。

我们来测试下这个结论:

User类

poYBAGLM5qaADmAWAAEkCBKh5h4352.jpg

pYYBAGLM5q6AIREwAAETOQGRbiE266.jpg

测试类

pYYBAGLM5uKAUZX_AAGU7j52Bic863.jpg

poYBAGLM5uiAQ0aVAAA7LL1_O6Y789.jpg

结果

先注释掉反序列化代码, 执行序列化代码, 然后修改User类signature = “我的眼里只有你”, 再注释掉序列化代码执行反序列化代码, 最后结果如下:

poYBAGLM5v-ALZ49AAB0bxxmfIk875.jpg

static属性为什么不会被序列化?

因为序列化是针对对象而言的,而static属性优先于对象存在,随着类的加载而加载, 所以不会被序列化。

看到这个结论,是不是有人会问,serialVersionUID也被static修饰,为什么serialVersionUID会被序列化? 其实serialVersionUID属性并没有被序列化,JVM在序列化对象时会自动生成一个serialVersionUID,然后将我们显示指定的serialVersionUID属性值赋给自动生成的serialVersionUID。

审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8504

    浏览量

    150844
  • JAVA
    +关注

    关注

    19

    文章

    2959

    浏览量

    104555
  • RPC
    RPC
    +关注

    关注

    0

    文章

    111

    浏览量

    11515

原文标题:Java 序列化和反序列化,为什么要实现 Serializable 接口?

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    常见的服务器容器和漏洞类型汇总

    常见的服务器容器包括KubeSphere、Tomcat、Nginx、Apache等,它们在提供便捷的服务部署和灵活的网络功能的同时,也可能存在着一定的安全风险。这些容器的漏洞可能导致数据泄露、权限被非授权访问甚至系统被完全控制。具体的常见服务器容器漏洞包括解析漏洞、SSRF以及JAVA反序列化等。
    的头像 发表于 08-29 10:39 195次阅读

    【「时间序列与机器学习」阅读体验】时间序列的信息提取

    的稳健缩放、时间序列的标准。 时间序列的特征工程、时间序列的统计特征、时间序列的熵特征、时间序列
    发表于 08-17 21:12

    【《时间序列与机器学习》阅读体验】+ 时间序列的信息提取

    之前对《时间序列与机器学习》一书进行了整体浏览,并且非常轻松愉快的完成了第一章的学习,今天开始学习第二章“时间序列的信息提取”。 先粗略的翻阅第二章,内容复杂,充斥了大量的定义、推导计算、代码,好在
    发表于 08-14 18:00

    【《时间序列与机器学习》阅读体验】+ 了解时间序列

    收到《时间序列与机器学习》一书,彩色印刷,公式代码清晰,非常精美。感谢作者,感谢电子发烧友提供了一个让我学习时间序列及应用的机会! 前言第一段描述了编写背景: 由此可知,这是一本关于时间序列进行大数
    发表于 08-11 17:55

    【「时间序列与机器学习」阅读体验】全书概览与时间序列概述

    他领域(如自然语言处理、计算机视觉等)的关联。 ●第2章“时间序列的信息提取”:介绍特征工程的核心概念及其在时间序列分析中的广用,比如对原始数据进行归一、缺失值填充等转换;以及如何通过特征工程从时间
    发表于 08-07 23:03

    python训练出的模型怎么调用

    使用pickle模块 pickle 是Python的一个内置模块,用于序列化反序列化Python对象结构。使用 pickle 可以方便地保存和加载模型。 import pickle # 保存模型
    的头像 发表于 07-11 10:15 1631次阅读

    数字序列信号发生器如何测量

    数字序列信号发生器(Digital Sequence Signal Generator,简称DSSG)是一种用于生成数字序列信号的设备。它广泛应用于通信、雷达、电子对抗等领域。本文将详细介绍数字序列
    的头像 发表于 06-03 14:04 370次阅读

    最新开源代码证实!“鸿蒙原生版”微信正在积极开发中

    生态。 MMKV 官方介绍 MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化 / 反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今在微信客户端
    发表于 05-08 17:08

    在嵌入式系统中集成Rust和Qt的实践

    Rust 拥有丰富的库生态系统,用于序列化反序列化、异步操作、解析不安全输入、线程、静态分析等,而 Qt 是一个 C++ 工具包,支持跨各种平台的丰富的、基于 GUI 的应用程序,从 iOS 到嵌入式Linux。Qt 应用程序包括表示业务逻辑的 C++ 插件
    发表于 05-03 10:26 1708次阅读
    在嵌入式系统中集成Rust和Qt的实践

    ROS机器人操作系统的实现原理

    面对序列化,很多人心中可能会有很多疑问。 首先,为什么序列化?或者更具体的说,既然对象的信息本来就是以字节的形式储存在内存中,那为什么多此一举把一些字节数据转换成另一种形式的、一维
    的头像 发表于 04-27 02:39 3018次阅读
    ROS机器人操作系统的<b class='flag-5'>实现</b>原理

    苹果将允许维修部分iPhone使用二手原装配件,但仍禁用第三方配件

    他指出,“零件序列化” 是一个广为人知且常带负面含义的词汇。许多人误解为苹果阻止 iPhone 使用第三方零件,然而事实并非如此。苹果的序列化匹配旨在确认设备中的部件真实性以及实现更精准的配合度。
    的头像 发表于 04-12 14:22 379次阅读

    鸿蒙原生应用开发-ArkTS语言基础类库多线程并发概述

    的一系列复杂偶发的问题,同时并发度也相对较高,因此得到了广泛的支持和使用,也是当前ArkTS语言选择的并发模型。 由于Actor模型的内存隔离特性,所以需要进行跨线程的数据序列化传输。 一、数据传输
    发表于 03-28 14:35

    俄勒冈州禁止数码设备使用“序列化”技术

    该法案对诸如苹果iPhone等数字产品产生巨大影响,意即制造商无法利用“零件序列化”技术束缚消费者选择第三方维修服务或自主修复非原产部件,同时也不能以此减少设备性能或误导使用者。
    的头像 发表于 03-28 10:46 507次阅读

    鸿蒙原生应用开发-ArkTS语言基础类库多线程并发概述

    的一系列复杂偶发的问题,同时并发度也相对较高,因此得到了广泛的支持和使用,也是当前ArkTS语言选择的并发模型。 由于Actor模型的内存隔离特性,所以需要进行跨线程的数据序列化传输。 一、数据传输
    发表于 03-22 15:40

    TSMaster 序列发送模块在汽车开发测试中的应用

    众所周知,序列发送模块可以不需要脚本代码实现测试中特定控制报文序列的发送,该模块多用于循环顺序控制的测试案例中。序列发送模块的常用场景,主要是针对一些新开发的产品需要通过该模块来验证产
    的头像 发表于 02-19 14:00 632次阅读
    TSMaster <b class='flag-5'>序列</b>发送模块在汽车开发测试中的应用