37. 【Java教程】序列化与反序列化

上一小节我们学习了 Java 的输入输出流,有了这些前置知识点,我们就可以学习 Java 的序列化了。本小节将介绍什么是序列化、什么是反序列化、序列化有什么作用,如何实现序列化与反序列化,Serializable 接口介绍,常用序列化工具介绍等内容。了解序列化的用途、学会如何进行序列化和反序列化操作是本小节的重点内容。

1. 序列化与反序列化

序列化在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式,以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始对象相同语义的副本。

很多编程语言自身就支持序列化操作。Java 语言提供自动序列化,序列化(serialize)就是将对象转换为字节流;与之相应对的,反序列化(deserialize)就是将字节流转换为对象。

需要注意的是,Java 序列化对象时,会把对象的状态保存成字节序列,对象的状态指的就是其成员变量,因此序列化的对象不会保存类的静态变量。

在 Java 中,可通过对象输出/输入流来实现序列化/反序列化操作。 java.io包中,提供了ObjectInputStream类和ObjectOutputStream用来序列化对象,这两个类我们将在下面介绍。下面我们来介绍一下序列化的作用。

2. 序列化的作用

  • 序列化可以将对象的字节序列存持久化:可以将其保存在内存、文件、数据库中(见下图);
  • 可以在网络上传输对象字节序列
  • 可用于远端程序方法调用

3. 实现序列化

  • ObjectOutputStream类下的void writeObject(Object obj)方法用于将一个对象写入对象输出流,也就是序列化;
  • ObjectInputStream类下的Object readObject()方法用于读取一个对象到输入流,也就是反序列化。

实例代码如下:

import java.io.*;

public class SerializeDemo1 {

    static class Cat implements Serializable {
        private static final long serialVersionUID = 1L;

        private String nickname;

        private Integer age;

        public Cat() {}

        public Cat(String nickname, Integer age) {
            this.nickname = nickname;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Cat{" +
                    "nickname='" + nickname + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    /**
     * 序列化方法
     * @param filepath 文件路径
     * @param cat 要序列化的对象
     * @throws IOException
     */
    private static void serialize(String filepath, Cat cat) throws IOException {
        // 实例化file对象
        File file = new File(filepath);
        // 实例化文件输出流
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        // 实例化对象输出流
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        // 保存cat对象
        objectOutputStream.writeObject(cat);
        // 关闭流
        fileOutputStream.close();
        objectOutputStream.close();
    }

    /**
     * 反序列化方法
     * @param filepath 文件路径
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private static void deserialize(String filepath) throws IOException, ClassNotFoundException {
        // 实例化file对象
        File file = new File(filepath);
        // 实例化文件输入流
        FileInputStream fileInputStream = new FileInputStream(file);
        // 实例化对象输入流
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        Object o = objectInputStream.readObject();
        System.out.println(o);
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String filename = "C:\\Users\\Colorful\\Desktop\\mybj\\Hello.txt";
        Cat cat = new Cat("猪皮", 1);
        serialize(filename, cat);
        deserialize(filename);
    }

}

运行结果:

Cat{nickname='猪皮', age=1}

上述代码中,我们定义了一个Cat类,它实现了Serializable接口,类内部有一个private static final long serialVersionUID = 1L;,关于这两点,我们下面紧接着就会介绍。

除了Cat类的定义,我们还分别封装了序列化与反序列化的方法,并在主方法中调用了这两个方法,实现了cat对象的序列化和反序列化操作。

在调用序列化方法后,你会发现磁盘中的Hello.txt文件中被cat对象写入了序列化后的数据:

4. Seralizable 接口

被序列化的类必须是EnumArraySerializable中的任意一种类型。

如果要序列化的类不是枚举类型和数组类型的话,则必须实现java.io.Seralizable接口,否则直接序列化将抛出NotSerializableException异常。

4.1 serialVersionUID

serialVersionUID 是 Java 为每个序列化类产生的版本标识。它可以用来保证在反序列化时,发送方发送的和接受方接收的是可兼容的对象。如果接收方接收的类的 serialVersionUID 与发送方发送的 serialVersionUID 不一致,会抛出 InvalidClassException

4.2 默认序列化机制

如果仅仅只是让某个类实现 Serializable 接口,而没有其它任何处理的话,那么就会使用默认序列化机制。

使用默认机制,在序列化对象时,不仅会序列化当前对象本身,还会对其父类的字段以及该对象引用的其它对象也进行序列化。同样地,这些其它对象引用的另外对象也将被序列化,以此类推。所以,如果一个对象包含的成员变量是容器类对象,而这些容器所含有的元素也是容器类对象,那么这个序列化的过程就会较复杂,开销也较大。

4.3 transient 关键字

在现实应用中,有些时候不能使用默认序列化机制。比如,希望在序列化过程中忽略掉敏感数据,或者简化序列化过程。下面将介绍若干影响序列化的方法。

当某个字段被声明为 transient 后,默认序列化机制就会忽略该字段

可以尝试将实例代码中Cat类的成员变量age声明为transient

// 仅部分代码
static class Cat implements Serializable {
    transient private Integer age;
}

运行程序,我们会发现成员变量age没有被序列化。

5. 常用序列化工具

Java 官方的序列化存在很多缺点,因此,开发者们更倾向于使用优秀的第三方序列化工具来替代 Java 自身的序列化机制。

Java 官方的序列化主要体现在以下方面:

  • 性能问题:序列化后的数据相对于一些优秀的序列化的工具,还是要大不少,这大大影响存储和传输的效率;
  • 繁琐的步骤:Java 官方的序列化一定需要实现 Serializable 接口,略显繁琐,而且需要关注 serialVersionUID
  • 无法跨语言使用:序列化的很大一个目的就是用于不同语言来读写数据。

下面列举了一些优秀的序列化工具:

  • thrift、protobuf - 适用于对性能敏感,对开发体验要求不高的内部系统。
  • hessian - 适用于对开发体验敏感,性能有要求的内外部系统。
  • jackson、gson、fastjson - 适用于对序列化后的数据要求有良好的可读性(转为 json 、xml 形式)。

6. 小结

通过本小节的学习,我们知道了序列化(serialize)就是将对象转换为字节流,反序列化(deserialize)就是将字节流转换为对象。想要实现序列化,就必须继承Seralizable接口,serialVersionUID 是 Java 为每个序列化类产生的版本标识。当某个字段被声明为 transient 后,默认序列化机制就会忽略该字段。学会根据自己的应用场景选择使用序列化工具。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE精炼宝库】多线程(4)深度理解死锁、内存可见性、volatile关键字、wait、notify

目录 一、死锁 1.1 出现死锁的常见场景: 1.2 产生死锁的后果: 1.3 如何避免死锁: 二、内存可见性 2.1 由内存可见性产生的经典案例: 2.2 volatile 关键字: 2.2.1 volatile 用法: 2.2.2 volatile 不…

C++中的stack和queue

C中的stack和queue 一丶stack1. stack的介绍2. stack的使用3. stack的模拟实现 二丶queue1. queue的介绍2. queue的使用3. queue的模拟实现 一丶stack 1. stack的介绍 stack的文档介绍 关于stack: 1. stack是一种容器适配器,专门用在具有后进先出操作的…

ROS socketcan_bridge使用说明

ROS socketcan_bridge使用说明(以ubuntu20.04为例) socketcan_bridge是什么 ROS针对socketcan提供了三个层次的驱动库,分别是ros_canopen,socketcan_bridge和socketcan_interface。 socketcan_interface: 功能&#x…

20240607在Toybrick的TB-RK3588开发板的Android12下适配IMX415摄像头和ov50c40

20240607在Toybrick的TB-RK3588开发板的Android12下适配IMX415摄像头和ov50c40 2024/6/7 11:42 【4K/8K摄像头发热量巨大,请做好散热措施,最好使用散热片鼓风机模式!】 结论:欢迎您入坑。 Toybrick的TB-RK3588开发板的技术支持不…

STM32—按键控制LED(定时器)

目录 1 、 电路构成及原理图 2 、编写实现代码 main.c exit.c 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 EXTI(External interrupt/event controller&#xff…

机器视觉——物块分拣

项目进行到第四天,我们学到了很多,可以进行实操。 首先我们利用相机软件进行采图 然后导入代码里面 完整代码 dev_get_window (WindowHandle) list_image_files (采图, default, [], ImageFiles) for Index : 0 to |ImageFiles| - 1 by 1read_image (Im…

上BFT,是你的首选

上BFT,是你的首选 如果你想要找最智能的机器人,想要找品牌最全或者想要咨询专业的解决方案,一定不要错过BFT机器人采购站。BFT致力于为广大用户提供品质卓越、技术先进的机器人产品。 BFT里面机器人多种多样,不管您是想要工业机器…

取证工作: SysTools MailXaminer, 用强大功能辅助电子邮件调查工作的每一步

天津鸿萌科贸发展有限公司是 SysTools 系列软件的授权代理商。 SysTools MailXaminer 电子邮件取证软件将调查工作分为五个阶段:邮件加载、预览、搜索、分析及导出。软件对调查工作的每一阶段都提供了现代高级功能,以帮助数字取证调查员根据其具体要求对…

知乎知+广告推广开户充值的返点政策是怎样?

如何让您的品牌精准触达目标受众,实现高效传播与转化,成为了每一位市场人面临的挑战。为此,云衔科技作为业界领先的数字营销解决方案提供商,正式宣布全面支持知乎知广告开户及一站式代运营服务,旨在帮助各行业客户在知…

珠海鸿瑞毛利率持续下滑:核心产品销量大降,偿债能力偏弱

《港湾商业观察》黄懿 日前,珠海市鸿瑞信息技术股份有限公司(下称“珠海鸿瑞”)收到了北京证券交易所发出的第三轮审核问询函。 此前,2020年11月,珠海鸿瑞曾向深交所报送上市申请。IPO申请文件获受理后,珠…

用互斥锁解决缓存击穿

我先说一下正常的业务流程:需要查询店铺数据,我们会先从redis中查询,判断是否能命中,若命中说明redis中有需要的数据就直接返回;没有命中就需要去mysql数据库查询,在数据库中查到了就返回数据并把该数据存入…

pypi 发布自己的包

注册pypi个人用户 网址:https://pypi.org 目录结构dingtalk_utils 必须-pkgs- __init__.py .gitignore LICENSE 必须 README.md 必须 requirements.txt setup.py 必须安装依赖 pip install setuptools wheel安装上传工具 pip install twinesetup.py i…

Maxkb玩转大语言模型

Maxkb玩转大语言模型 随着国外大语言模型llama3的发布,搭建本地个人免费“人工智能”变得越来越简单,今天博主分享使用Max搭建本地的个人聊天式对话及个人本地知识域的搭建。 1.安装Maxkb开源应用 github docker快速安装 docker run -d --namemaxkb -p 8…

进入某个页面时将VUE中的某个Button按钮设置为选中状态

进入某个页面时将VUE中的某个Button按钮设置为选中状态 我想达到的效果如标题所说,目的是为了表示页面展示的内容是由于该按钮被选择的结果。 解决思路是使用VUE中的mounted()钩子函数,在该函数中调用按钮得到焦点方法、按钮被点击方法。具体代码如下&am…

Redis限流方案

限流简介 限流算法在分布式领域是一个经常被提起的话题,当系统的处理能力有限时,如何阻止计划外的请求继续对系统施压,是一个需要重视的问题。 除了控制流量,限流还有一个应用目的是用于控制用户行为,避免垃圾请求&a…

【echarts】如何制作,横坐标每个日期点如何对应一条竖线的图,以及 markline设置后不生效问题

图的样式如下: 在线演示 每一个日期,对应一条竖线展示。 echarts配置内容: 在线演示 option {xAxis: {type: category,data: [20240601, 20240602, 20240603, 20240604, 20240605, 20240606, 20240607] // X轴数据},yAxis: {type: valu…

Bond 网卡绑定技术学习

前言: 为了实现网卡的高可用性,需要学习一下 Bond技术 1. 概念 Bond(也被称为链路聚合、端口绑定或接口绑定)是一种网络技术,用于将多个物理网络接口(如以太网接口)组合成一个逻辑接口。这样做…

今日份动态规划学习

主要只搞了一个这道题,有点摸鱼了今天晚上,也是来小看一下这道题吧01背包完全背包 P1941 [NOIP2014 提高组] 飞扬的小鸟 题意: 这题是说,给我们一个游戏界面,界面的长度为n(水平距离)&#x…

E: Unable to locate package ros-kinetic-usb-cam

mkdir -p USB/src && cd USB/src catkin_init_workspace git clone https://github.com/bosch-ros-pkg/usb_cam.git cd .. catkin_make source devel/setup.bash echo "source ~/USB/devel/setup.bash" >> ~/.bashrc source ~/.bashrc 编译过程报错&…

Wireshark抓包日常运维实用过滤

0x0 Wireshark 介绍 Wireshark 是一款功能强大的网络分析工具,适用于网络专业人员。它提供了出色的过滤器,您可以轻松放大到您认为可能存在问题的位置。过滤器的主要好处是消除定位流量,并缩小要查找的数据类型。 0x1 根据源 IP 地址过滤主…