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

    文章

    7616

    浏览量

    148379
  • JAVA
    +关注

    关注

    19

    文章

    2904

    浏览量

    102978
  • RPC
    RPC
    +关注

    关注

    0

    文章

    102

    浏览量

    11419

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

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

收藏 人收藏

    评论

    相关推荐

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

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

    浅析闭源系统下的Evilparcel漏洞

    Evilparcel漏洞可以导致Bundle在多次序列化反序列化过程中内容发生改变。结合LAW跳板,可以实现权限提升,严重影响系统安全
    发表于 11-16 14:43 157次阅读
    浅析闭源系统下的Evilparcel漏洞

    什么时候需要Boost序列化

    程序开发中,序列化是经常需要用到的。像一些相对高级语言,比如JAVA, C#都已经很好的支持了序列化,那么C++呢?当然一个比较好的选择就是用Boost,这个号称C++准标准库的东西。 什么时候需要
    的头像 发表于 11-10 10:14 198次阅读

    protobuf的编码和存储方式

    一、protobuf简介: 1.1 protobuf的定义: protobuf是用来干嘛的? protobuf是一种用于 对结构数据进行序列化的工具,从而实现 数据存储和交换。 (主要用于网络通信
    的头像 发表于 11-09 09:27 435次阅读
    protobuf的编码和存储方式

    Java序列化怎么使用

    转换方式就叫做序列化。将文件或者网络传输中得到的 byte[] 数组转换为 java 对象就叫做反序列化。 怎么使用 如果一个 Java 对象要能被序列化,必须实现一个特殊
    的头像 发表于 10-10 14:19 242次阅读

    Spring Boot时配置JSON序列化选项的几种方法

    在Spring Boot Web 项目中,当使用JSON格式接收数据和返回数据的时候,Spring Boot 默认使用一个ObjectMapper实例来序列化响应和反序列化请求。 在本文中,我们
    的头像 发表于 10-09 10:26 1239次阅读

    如何用C语言进行json的序列化反序列化

    json是目前最为流行的文本数据传输格式,特别是在网络通信上广泛应用,随着物联网的兴起,在嵌入式设备上,也需要开始使用json进行数据传输,那么,如何快速简洁地用C语言进行json的序列化反序列化
    的头像 发表于 10-07 11:05 814次阅读

    如何使用Serde进行序列化反序列化

    Serde 是一个用于序列化反序列化 Rust 数据结构的库。它支持 JSON、BSON、YAML 等多种格式,并且可以自定义序列化反序列化方式。Serde 的特点是代码简洁、易于
    的头像 发表于 09-30 17:09 831次阅读

    ROS中的序列化实现

    理解了序列化,再回到ROS。我们发现,ROS没有采用第三方的序列化工具,而是选择自己实现,代码在roscpp_core项目下的roscpp_serialization中,见下图。这个功能涉及的代码
    的头像 发表于 09-14 17:26 585次阅读

    什么是序列化 为什么要序列化

    什么是序列化? “序列化”(Serialization )的意思是将一个对象转化为字节流。 这里说的对象可以理解为“面向对象”里的那个对象,具体的就是存储在内存中的对象数据。 与之相反的过程是“
    的头像 发表于 09-14 17:22 1487次阅读
    什么是<b class='flag-5'>序列化</b> 为什么要<b class='flag-5'>序列化</b>

    基于反序列化过采样数据的时钟和数据恢复单元

    电子发烧友网站提供《基于反序列化过采样数据的时钟和数据恢复单元.pdf》资料免费下载
    发表于 09-13 10:41 0次下载
    基于<b class='flag-5'>反序列化</b>过采样数据的时钟和数据恢复单元

    蚂蚁集团开源高性能多语言序列化框架Fury解读

    Fury 是一个基于 JIT 动态编译和零拷贝的多语言序列化框架,支持 Java/Python/Golang/JavaScript/C++ 等语言,提供全自动的对象多语言 / 跨语言序列化能力,和相比 JDK 最高 170 倍的性能。
    的头像 发表于 08-25 17:05 727次阅读
    蚂蚁集团开源高性能多语言<b class='flag-5'>序列化</b>框架Fury解读

    JVM源码分析之不保证顺序的Class.getMethods

    如果大家看过或者实现序列化反序列化的代码,这个问题就不难回答了,今天碰到的这个问题其实是发生在大家可能最常用的`fastjson`库里的,所以如果大家在使用这个库,请务必检查下你的代码,以免踩到此坑
    的头像 发表于 06-27 15:22 333次阅读

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

    本文介绍ROS机器人操作系统(Robot Operating System)的实现原理,从最底层分析ROS代码是如何实现的。 **1、序列化** 把通信的内容(也就是消息message)
    的头像 发表于 05-19 17:42 858次阅读

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

    本文介绍ROS机器人操作系统(Robot Operating System)的实现原理,从最底层分析ROS代码是如何实现的。 **1、序列化** 把通信的内容(也就是消息message)
    的头像 发表于 05-19 17:41 769次阅读
    ROS机器人操作系统的<b class='flag-5'>实现</b>原理(上)