Serializable接口解读

2023-10-27

Serializable 接口

作为 Java 中那些绕不开的内置接口 Serializable这个接口的全限定名(包名 + 接口名)是 java.io.Serializable,这里给大家说个小技巧,当你看到一个类或者接口的包名前缀里包含java.io那就证明这个类 / 接口它跟数据的传输有关。

Serializable 是 Java 中非常重要的一个接口,如果一个类的对象是可序列化的,即对象在程序里可以进行序列化和反序列化,对象的类就一定要实现Serializable接口。那么为什么要进行序列化和反序列化呢?

序列化的意思是将对象的状态转换为字节流;反序列化则相反。换句话说,序列化是将 Java 对象转换为静态字节流(序列),然后我们可以将其保存到文件、数据库或者是通过通过网络传输,反序列化则是在我们读取到字节流后再转换成 Java 对象的过程;这也正好解释了为什Serializable 接口会归属到java.io包下面。

Serializable 是一个标记型接口

虽说需要进行序列化的对象,它们的类都需要实现 Serializable 接口,但其实你会发现,我们在让一个类实现 Serializable 接口时,并没有额外实现过什么抽线方法。

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;
}

比如向上面个类文件里的内容,Person 类声明实现 Serializable 接口后,并没有去实现什么抽象方法,IDE 也不会用红线警告提示我们:“你有一个抽象方法需要实现” ,原因是 Serializable 接口里并没有声明抽象方法。

public interface Serializable {
}

这种不包含任何方法的 interface 被称为标记型接口,类实现 Serializable接口不必实现任何特定方法,它只起标记作用,让 Java 知道该类可以用于对象序列化。

serializable Version UID

虽说一个类实现了 Serializable 接口的时候不需要实现特定的方法,但是经常会看到一些实现了Serializable的类中,都有一个名为serialVersionUID类型为long的私有静态 属性。

import java.io.Serializable;

public static class Person implements Serializable {

    private static final long serialVersionUID = -7792628363939354385L;

    public String name;
    public int    age;
}

该属性修饰符里使用了final即赋值后不可更改。Java 的对象序列化 API 在从读取到的字节序列中反序列化出对象时,使用 serialVersionUID 这个静态类属性来判断:是否序列化对象时使用了当前相同版本的类进行的序列化。Java 使用它来验证保存和加载的对象是否具有相同的属性,确保在序列化上是兼容的。

大多数的 IDE 都可以自动生成这个 serialVersionUID静态属性的值,规则是基于类名、属性和相关的访问修饰符。任何更改都会导致不同的数字,并可能导致 InvalidClassException。 如果一个实现 Serializable 的类没有声明 serialVersionUID,JVM 会在运行时自动生成一个。但是,强烈建议每个可序列化类都声明 serialVersionUID,因为默认生成的serialVersionUID依赖于编译器,因此可能会导致意外的InvalidClassExceptions

Java 序列化与JSON序列化的区别

Java 的序列化与现在互联网上 Web 应用交互数据常用的 JSON 序列化并不是一回事儿,这是咱们需要注意的,像 Java、C#、PHP 这些编程语言,都有自己的序列化机制把自家的对象序列化成字节然后进行传输或者保存,但是这些语言的序列化机制之间并不能互认,即用 Java 把对象序列化成字节、通过网络 RESTful API 传给一个 PHP 开发的服务,PHP 是没办法反序列化还原出这个对象的。这样才有了 JSON、XML、Protocol Buffer 这样的更通用的序列化标准。

Java序列化相较于 JSON 的优势

上面介绍了 JSON 这样的通用序列化格式的优势,有的可能会问了,那还用 Java 序列化干啥。这里再给大家分析一下,Java 对象序列化虽然在通用性上不如 JSON 那些序列化格式,但是在 Java 生态内部却是十分好用的,其最聪明的一点是,它不仅能保存对象的副本,而且还会跟着对象里面的reference,把它所引用的对象也保存起来,然后再继续跟踪那些对象的reference,以此类推。

是不是所有的bean都需要进行序列化?

首先第一个问题,实现序列化的两个原因:

1、将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本;

2、按值将对象从一个应用程序域发送至另一个应用程序域。实现serializabel接口的作用是就是可以把对象存到字节流,然后可以恢复,所以你想如果你的对象没实现序列化怎么才能进行持久化和网络传输呢,要持久化和网络传输就得转为字节流,所以在分布式应用中及设计数据持久化的场景中,你就得实现序列化。

第二个问题,是不是每个实体bean都要实现序列化,答案其实还要回归到第一个问题,那就是你的bean是否需要持久化存储媒体中以及是否需要传输给另一个应用,没有的话就不需要,例如我们利用fastjson将实体类转化成json字符串时,并不涉及到转化为字节流,所以其实跟序列化没有关系。

第三个问题,有的时候并没有实现序列化,依然可以持久化到数据库。这个其实我们可以看看实体类中常用的数据类型,例如Date、String等等,它们已经实现了序列化,而一些基本类型,数据库里面有与之对应的数据结构,从我们的类声明来看,我们没有实现serializabel接口,其实是在声明的各个不同变量的时候,由具体的数据类型帮助我们实现了序列化操作。

另外需要注意的是,在NoSql数据库中,并没有与我们Java基本类型对应的数据结构,所以在往nosql数据库中存储时,我们就必须将对象进行序列化,同时在网络传输中我们要注意到两个应用中javabean的serialVersionUID要保持一致,不然就不能正常的进行反序列化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Serializable接口解读 的相关文章

随机推荐

  • 基于 NULL 符号的 R 语言编程探索

    基于 NULL 符号的 R 语言编程探索 在 R 语言中 NULL 是一个特殊的数据类型 代表空值或者缺失值 它在很多情况下都有重要的作用 特别是在函数的返回值 条件判断和变量初始化等方面 在本文中 我们将探索如何使用 NULL 符号来优化
  • visual studio +libtorch +cuda 11.3 配置pytorch C++环境

    visual studio libtorch cuda 11 3 配置pytorch C 环境 1 首先进入pytorch官网下载对应版本的libtorch 如果你需要安装GPU版本那么在前面你需要提前在本地下载安装好相应版本的cuda环境
  • Linux下的汇编程序设计

    一 汇编语言的优缺点 由于Linux是用C写的 所以C自然而然的就成为了Linux的标准编程语言 大部分人都把汇编给忽略了 甚至在因特网上找资料都是非常的困难 很多问题都需要靠自己来尝试 我认为这样对待汇编语言是不公平的 不能只看到它的缺点
  • 课时 8 自测题

    Pod 中引用 ConfigMap 不正确的是 单选题 A 环境变量 B 命令行参数 C 资源声明 D Volumes 如下哪些方式创建的 Pod 可以使用 ConfigMap 多选题 A Kubectl B Dashboard C kub
  • Ajax 上传文件原理,ajax上传文件obs

    ajax上传文件obs 内容精选 换一换 小文件 小于100MB的文件 打开Notebook实例 单击右上角Upload 将本地文件直接上传至Notebook中 上传小文件打开Notebook实例 单击右上角Upload 将本地文件直接上传
  • sgi_stl源码学习,解析set、map背后的_Rb_tree源码(未完待续)

    参考资料 chatGPT先推荐的 算法导论 第13章 不过我手头没有这本书 https www cnblogs com skywang12345 p 3245399 html chatGPT推荐的 外加sgi stl源码 个人觉得通过源码理
  • 问遍大佬,看遍百文,呕心沥血整理出的一线最值得加入的互联网大厂,必收藏

    打工人 打工魂 打工进大厂才是人上人 现在很多人选择了去一线城市打工 赚钱 积累经验与资历 到了一定年龄 回二线城市生活定居 IT行业做技术很公平 没那么看重出身 只要你技术好 能力强 就能进大厂 拿高薪 IT行业算是目前为数不多的比较容易
  • Unity3D实战【八】Animator 动画控制器

    一 创建文件夹Prefabs 存放预制体 和Animations 存放动画相关 给人物改个名字 Player Add Component gt Animator 把人物拖到Prefabs文件夹里 在Animations文件夹下建一个文件夹A
  • 随机生成验证码(Java实现)

    需求 定义方法实现随机产生一个5位的验证码 每位可能是数字 大写字母 小写字母 分析 定义一个方法 生成验证码返回 方法参数是位数 方法的返回值类型是String 在方法内部使用for循环生成指定位数的随机字符 并连接起来 把连接好的随机字
  • 选项式api V/S 组合式api

    Options 选项式api 特点 多个选项的对象来描述组件的逻辑 例如data选项写数据 methods选项写函数 一个功能逻辑的代码分散 选项所定义的属性都会暴露在函数内部的 this 上 它会指向当前的组件实例 优点 易于学习和使用
  • selenium的安装和下载谷歌浏览器镜像驱动

    selenium安装 Selenium是一个用于web自动化测试的框架 在使用Ajax请求数据的页面中 会出现 sign token等密钥 如果考虑去破解可能花费的精力较多 所以考虑借助使用Selenium框架来实现数据爬取 如果没安装se
  • tensorflow学习率控制及调试

    在深度学习中 学习率变化对模型收敛的结果影响很大 因此很多时候都需要控制学习率的变化 本文以tensorflow实现learning rate test为例 讲述学习率变化控制的方法 以及怎么调试 一 learning rate test
  • ThreadLocal使用

    1 简介 ThreadLocal类用来提供线程内部的局部变量 不同的线程之间不会相互干扰 这种变量在多线程环境下访问 通过get和set方法访问 时能保证各个线程的变量相对独立于其他线程内的变量 在线程的生命周期内起作用 可以减少同一个线程
  • HCIA/HCIP使用eNSP模拟OSPF综合应用场景(虚链路 特殊区域 认证 引入外部路由)

    OSPF综合应用场景 配套实验拓扑 OSPF Comprehensive Application Experiment topo 目录 OSPF综合应用场景 拓扑预览 一 基础配置 1 配置R1 2 配置R2 3 配置R3 4 配置R4 5
  • asp.net ajax 参数,ASP.NET jquery ajax传递参数

    第一种 GET传递 前台 ajax GET 传递 即在请求的地址后面加上参数 URL地址长度有显示 安全性低 后台接收 Request QueryString 参数名字 例如 function LoadBar id var project
  • 烂大街的TCP/IP网络模型,你真的懂了?

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 目录 一 面试真题 二 面试官心理分析 三 面试题剖析 一 面试真题 你能聊聊TCP IP 的四层网络模型和 OSI 七层网络模型吗 二 面试官心理分析 为啥要问这个
  • 微信支付二维码native原生支付开发模式一

    开发前 商户必须在公众平台后台设置支付回调URL URL实现的功能 接收用户扫码后微信支付系统回调的productid和openid URL设置详见回调地址设置 1 业务流程时序图 图6 8 原生支付接口模式一时序图 业务流程说明 1 商户
  • 关于JAVA 并发类的Executor误用导致的线程数量异常

    近期在项目中 在方法中局部使用 Executor创建固定线程 没有按照要求在局部用完之后进行shutdown操作 导致每次方法调用都会生成一个线程池 由于固定线程池在生成线程之后 不会自动回收 一致处于 run 状态等待任务的到达 因此导致
  • Qt Creator 无效构建套件(Kits)的清除以及恢复默认设置

    Qt Creator 无效构建套件 Kits 的清除以及恢复默认设置 在使用在Qt Creator 开发过程中 有时候由于配置的原因出现了很多无效的构建套件 Kits 在创建项目也会列出来 因此想清理掉这些的无效的Kit 再有就是将Qt的配
  • Serializable接口解读

    Serializable 接口 作为 Java 中那些绕不开的内置接口 Serializable这个接口的全限定名 包名 接口名 是 java io Serializable 这里给大家说个小技巧 当你看到一个类或者接口的包名前缀里包含ja