首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

讲讲Java的序列化反序列化?

编程知识
2024年08月24日 20:21
  • 序列化:把对象转换为字节序列的过程称为对象的序列化.
  • 反序列化:把字节序列恢复为对象的过程称为对象的反序列化.

什么时候会用到

当只在本地 JVM 里运行下 Java 实例,这个时候是不需要什么序列化和反序列化的,但当出现以下场景时,就需要序列化和反序列化了:

  • 当需要将内存中的对象持久化到磁盘,数据库中时
  • 当需要与浏览器进行交互时
  • 当需要实现 RPC 时

但是当我们在与浏览器交互时,还有将内存中的对象持久化到数据库中时,好像都没有去进行序列化和反序列化,因为我们都没有实现 Serializable 接口,但一直正常运行?

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

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

public final class String implements java.io.Serializable,Comparable<String>,CharSequence {
    /\*\* The value is used for character storage. \*/
    private final char value\[\];

    /\*\* Cache the hash code for the string \*/
    private int hash; // Default to 0

    /\*\* use serialVersionUID from JDK 1.0.2 for interoperability \*/
    private static final long serialVersionUID = -6849794470754667710L;

    ......
}

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

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

<insert parameterType="org.tyshawn.bean.User">
    INSERT INTO t\_user(name,age) VALUES (#{name},#{age})
</insert>

实际上并不是将整个对象持久化到数据库中,而是将对象中的属性持久化到数据库中,而这些属性(如Date/String)都实现了 Serializable 接口。

为什么要实现 Serializable 接口?

在 Java 中实现了 Serializable 接口后, JVM 在类加载的时候就会发现我们实现了这个接口,然后在初始化实例对象的时候就会在底层实现序列化和反序列化。如果被写对象类型不是String、数组、Enum,并且没有实现Serializable接口,那么在进行序列化的时候,将抛出NotSerializableException。源码如下:

// remaining cases
if (obj instanceof String) {
    writeString((String) obj, unshared);
} else if (cl.isArray()) {
    writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
    writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
    writeOrdinaryObject(obj, desc, unshared);
} else {
    if (extendedDebugInfo) {
        throw new NotSerializableException(
            cl.getName() + "\n" + debugInfoStack.toString());
    } else {
        throw new NotSerializableException(cl.getName());
    }
}

为什么要显示指定 serialVersionUID 的值?

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

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

当然了,如果类写完后不再修改,那么不指定serialVersionUID,不会有问题,但这在实际开发中是不可能的,类会不断迭代,一旦类被修改了,那旧对象反序列化就会报错。 所以在实际开发中,都会显示指定一个 serialVersionUID。

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

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

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

不同序列化工具之间的权衡

不同序列化工具的权衡

  • 容量
  • 可读性
  • 操作难易
  • 性能
  • 兼容性

transient关键字

Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。

也就是说被transient修饰的成员变量,在序列化的时候其值会被忽略,在被反序列化后, transient 变量的值被设为初始值, 如 int 型的是 0,对象型的是 null。

关于作者

来自一线程序员Seven的探索与实践,持续学习迭代中~

本文已收录于我的个人博客:https://www.seven97.top

公众号:seven97,欢迎关注~

From:https://www.cnblogs.com/seven97-top/p/18378282
本文地址: http://www.shuzixingkong.net/article/1411
0评论
提交 加载更多评论
其他文章 玄机蓝队靶场_应急响应_02:apache日志分析
日志分析这块,感觉都是对grep、awk、sort、wc、uniq,这几个命令的使用。 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apache2 里边只有两种类型的日志,access.log和error.log。 access.log(访
.NET 音频采集
本文介绍Windows下声音数据的采集,用于本地录音、视讯会议、投屏等场景 声音录制有麦克风、扬声器以及混合录制三类方式,麦克风和扬声器单独录制的场景更多点,混合录制更多的是用于本地录音 我们基于NAudio实现,开源组件NAudio已经很稳定的实现了各类播放、录制、转码等功能,WaveIn,Wav
CSP-J 第一轮 2024模拟卷-1
单项选择题 我只写重点!!! 第四题 NOI复赛评测机所用的Linux系统属于() A.UML B.IDE C.OS D.Database 答案:C 解析:UML是一种建模语言,IDE是集成开放环境,Database是数据库,NOI复赛评测机所用的Linux系统属于OS(Operating Syst
预设型 DP
预设型 DP 《美好的一天》--青春学概论 한 잔 술에 취해 잠긴 목엔 沉醉于一杯酒 갈라지는 목소린 다시 带着沙哑的嗓音 두 잔 자기 전엔 기분 좋음 入睡前饮下第二杯让心情愉悦 알 수 없는 세상에 빠져 陷入不可预知的世界 세 잔 또 네 잔 술에 빠진 又沉醉于第三杯第四杯 세상과
预设型 DP 预设型 DP
apr库编译及队列使用笔记
操作系统 :CentOS 7.9_x64 apr库版本:apr-1.7.4 &amp; apr-util-1.6.3 gcc 版本:4.8.5 队列功能在C++或Python等脚本语言里面,是很容易就可以使用的,但C语言里面,标准库里面没有。 在使用C语言开发新应用时,就会遇到这个问题。阅读Free
apr库编译及队列使用笔记 apr库编译及队列使用笔记 apr库编译及队列使用笔记
Transformer模型:Position Embedding实现
在自然语言处理(NLP)中,Transformer 模型是一个非常重要的里程碑,它通过自注意力(self-attention)机制极大地提高了处理序列数据的能力。在 Transformer 模型中,词嵌入(Word Embedding)是输入层的关键部分,负责将离散的单词转换成连续的向量表示,以便模
全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列
在 Python 中,列表(list)是一种非常灵活的数据结构,可以用来实现堆栈(stack)、队列(queue)和双端队列(deque)。这些数据结构虽然在使用时遵循不同的操作规则,但都可以通过 Python 列表来高效地实现。
全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列 全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列 全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列
程序员:全栈的痛你不知道
我这里说的全栈,不只是IT技术栈,还有更多的是产品运营思维。任何时候全栈人都应该用解决问题、推动事情往前发展的思维去做事。
程序员:全栈的痛你不知道