Java序列化和反序列化

Java中的transient关键字深度解析 通过实现和readObject// 自定义加密处理// 自定义解密。 阅读详情

1、是什么?

序列化:就是把 Java 对象转换成字节序列的过程;
反序列化:就是把字节序列恢复为 Java 对象的过程;

2、为什么?

Java 序列化机制的作用:
(1)可以把对象以字节序列的方式持久化保存到到文件中;
(2)可以将对象以字节序列的方式在网络上进行传输;

3、怎么用?

  • 对于基本数据类型:都是可序列化的;
  • 对于引用数据类型:一个Java对象要想实现序列化,必须实现 java.io.Serializable 接口,该接口是一个标记接口,内部没有定义任何方法;
/**
 * ...
 * @author  unascribed
 * @see java.io.ObjectOutputStream
 * @see java.io.ObjectInputStream
 * @see java.io.ObjectOutput
 * @see java.io.ObjectInput
 * @see java.io.Externalizable
 * @since   JDK1.1
 */
public interface Serializable {
}

Java 中通过对象输入输出流来实现序列化和反序列化:

  • java.io.ObjectOutputStream 类实现对象的序列化;
  • java.io.ObjectInputStream 类实现反序列化回对象;

示例:
下面是实现了序列化接口的 Person 类和一个实现序列化接口的 Car 类:

@Getter
@Setter
@ToString
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    String name;
    int age;
    private Float height;
    //另一个对象
    List<Car> cars;
    //静态属性
    static String color = "unknown";
    //被 transient 修饰的属性
    transient Double salary;
}
@Getter
@Setter
@ToString
public class Car implements Serializable {

    private static final long serialVersionUID = 111L;

    private String brand;
    private Double price;
}

下面通过 ObjectOutputStream 将 Person 类的对象序列化后保存到 person.ser 文件中;

    @Test
    public void testSerialize() {
        //1、定义一个 Person 对象,并设置属性值
        Person person = new Person();
        person.setName("小明");
        person.setAge(25);
        person.setHeight(175.50f);
        person.setSalary(6700.00);
        Car car = new Car();
        car.setBrand("BMW");
        car.setPrice(200000.23);
        Car car2 = new Car();
        car2.setBrand("BYD");
        car2.setPrice(150000.5);
        List<Car> cars = new ArrayList<>();
        cars.add(car);
        cars.add(car2);
        person.setCars(cars);
        System.out.println("序列化对象: " + person);
        System.out.println("color: " + Person.color);

        //2、使用 ObjectOutputStream 将对象序列化后保存到文件中
        FileOutputStream os = null;
        ObjectOutputStream oos = null;
        try {
            os = new FileOutputStream("person.ser");
            oos = new ObjectOutputStream(os);
            oos.writeObject(person);
            oos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (oos != null) {
                    oos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

//打印结果:
序列化对象: Person(name=小明, age=25, height=175.5, cars=[Car(brand=BMW, price=200000.23), Car(brand=BYD, price=150000.5)], salary=6700.0)
color: unknown

接着,通过 ObjectInputStream 将 person.ser 文件反序列化成 Person 对象读取到内存中:

    @Test
    public void testDeserialize() {
        //1、使用 ObjectInputStream 将文件中的内容反序列化成 Person 对象
        InputStream is = null;
        ObjectInputStream ois = null;
        try {
            is = new FileInputStream("person.ser");
            ois = new ObjectInputStream(is);
            Person p = (Person) ois.readObject();
            System.out.println("反序列化对象: " + p);
            System.out.println("color: " + Person.color);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    
// 打印结果:
反序列化对象: Person(name=小明, age=25, height=175.5, cars=[Car(brand=BMW, price=200000.23), Car(brand=BYD, price=150000.5)], salary=null)
color: unknown

4、注意点:

(1)一个对象想要实现序列化,必须实现 Serializable 接口,并且其内部所有属性也必须都是可序列化的类型;
例如:如果 Person 类没有实现序列化,或者其内部的属性 Car 类没有实现序列化接口,在对 Person 对象进行序列化时,就会抛出 java.io.NotSerializableException 异常;
(2)对实现 Serializable 接口的类,通常情况下,最好需要显式的定义 serialVersionUID 字段,该字段的作用是为每个序列化类定义一个版本标识,用来保证反序列化时,遇到类的版本不兼容抛出异常;
例如:在使用 ObjectOutputStream 序列化 Person 对象时,其定义的 serialVersionUID = 1L; 但是,如果在反序列化时,其 serialVersionUID 修改为 2L; 就会抛出 java.io.InvalidClassException 异常;
(3)如果对于类中的某些属性不想被序列化,可以使用 transient 关键字修饰;
例如:对于 Person 对象中的 salary 属性,在序列化设置值为 6700.00,但是,在反序列化成的 Person 对象后,其值是默认的 null;
(4)如果父类实现序列化接口,子类继承父类,子类也是可序列化的;
(5)如果子类实现序列化接口,父类没有实现序列化,在进行序列化时,父类的属性不会被序列化,只会序列化子类自己的属性;
(6)静态属性不会被序列化;
(7)反序列化时,由JVM直接构造出Java对象,不会调用构造方法,构造方法内部的代码,在反序列化时不会执行。

5、Java 序列化的不足

  • 不能跨语言:Java 序列化仅适用于 Java 语言,不能够跨语言使用;
  • 存在安全性问题:反序列化是不用经过构造方法,可以将类路径上几乎所有实现了 Serializable 接口的对象都实例化。这意味着,在反序列化字节流的过程中,该方法可以执行任意类型的代码,这是非常危险的。
  • 性能太差:Java 的序列化耗时比较大。

6、其他方式

实际工作中,一般会使用其他方式替代 Java 的序列化,目前常用的方式就是 通过JSON这样的通用数据结构来实现,本质上就是一个特殊结构的字符串;另外,还有其他的一些优秀的序列化框架,如:protobuf、thrift 等。

7、补充

Java 中还有一个实现序列化的接口 Externalizable,其也是继承了 Serializable 接口,这里就不再赘述,后期有机会的话会补充。

参考地址:
深入理解 Java 序列化
序列化

动态规划2-最长公共子序列 参考 http://open.163.com/newview/movie/free?pid=M6UTT5U0I&mid=M6V2U1HL4 问题是给定字符串x和y,求出两个当中最长的公共子序列。比如x=abcdef y=acefg,那么他们的最长公共子序列就是acef。就是求x的所有可能的子字符串与y所有的子字符串匹配,如果相同,那么就是一个公共子序列,然后求最长的一个。 建议观看上... 阅读详情

相关推荐

最长公共子序列(动态规划)

最长公共子序列 最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问题都和这个问题一个套路,比如说编辑距离。而且,这个算法稍加改造就可以用于解决其他问题,所以说 LCS 算法是值得掌握的。 题目就是让我们求两个字符串的 LCS 长度: 输入: s1 = "babcde", s2 = ...

Mk_kkkk的博客 1655

Java基础—序列化关键字transient

原文作者:老鼠只爱大米 原文地址:Java中transient关键字的详细总结 一、概要介绍 本文要介绍的是Java中的transient关键字,transient是短暂的意思。对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。 因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。 (1)序列化 Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含...

sanmi8276的博客 3229

java序列化和反序列化

计算机中最基本的存储单位是字节 Byte, 任何数据最终都会被编码成字节序列,1byte=8bit, 一个字节等于八位,每一位都是用0 和 1 组成。在内存中,数据就是以 0 和 1 组成的二进制形式存储的,而字节数据在传输(如网络传输)或读写(如文件操作、数据库操作)时,通常以 "流"(的形式处理(即按顺序逐个字节传输 / 读写),这个流称为二进制流 (注: IO 支持的数据格式就是字节数组)。 我们平时写程序的时侯,如果要把运行中的 java 对象保存到数据库、文件或者通过网络传输,就需要把这些对象转

程序员一博 974

MySQL中使用序列-Sequence

在Oracle数据库中若想要一个连续的自增的数据类型的值,可以通过创建一个sequence来实现。而在MySQL数据库中并没有sequence。通常如果一个表只需要一个自增的列,那么我们可以使用MySQL的auto_increment(一个表只能有一个自增主键)。若想要在MySQL像Oracle中那样使用序列,我们该如何操作呢? 例如存在如下表定义: create table `t_user`( `id` bigint auto_increment primary key, ...

奔跑的蜗牛 1万+

在VSCode中使用LaTex+(grammarly语法检测,chatgpt翻译,Sumatra PDF 轻量级pdf阅读器)

整个文章分为以下几个内容,打 * 的是必须要安装的。

u011895157的博客 2万+

别再只接个放大器了!压电传感器测量电路(电压/电荷放大器)的5个实战配置要点

本文深入解析压电传感器测量电路中的5个关键实战配置要点,包括电缆长度选择、输入阻抗匹配、过载保护设计、低频噪声抑制及放大器选型策略。特别针对电压放大器和电荷放大器的应用场景差异提供工程实践建议,帮助工程师有效解决信号失真、噪声干扰等常见问题,提升测量精度和系统可靠性。

weixin_26869081的博客 302

【Java】序列化和反序列化

而这个writeString()往往是这样写的,字符串长度(不是大小)小于两个字节,就先写入一个字节的TC_STRING(16进制 74),然后调用writeUTF(),写入一个signature,这好像跟jvm有关。要使用一个类,就要先把它加载到虚拟机中,在加载完类之后,堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个class对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像一面镜子,透过镜子可以看到类的结构,所以形象的称之为:反射。

double222222的博客 1211

从零开始:如何用Python手绘波特图并分析电路稳定性

本文详细介绍了如何使用Python绘制波特图并分析电路稳定性,涵盖从基础理论到实际应用的完整流程。通过NumPy和Matplotlib实现频域分析,包括RC低通滤波器和RLC带通滤波器的案例,以及相位裕度计算等高级技巧,为电子工程师提供了一套高效的电路分析解决方案。

hhh00的博客 371

Java 序列化和反序列化

可以通过实现 readObject 方法来自定义反序列化过程。例如,可以在反序列化时对字段进行额外的验证或初始化。// 不会被默认序列化// 自定义反序列化逻辑// 默认反序列化// 手动反序列化 age// 自定义序列化逻辑// 默认序列化// 手动序列化 age@Override// 序列化// 反序列化。

qq_33807380的博客 1634

PCB工艺-SI9000使用教程

本文介绍了阻抗计算工具SI9000的使用方法,重点讲解了微带线与带状线的区别、共面阻抗概念及参考面选择。通过USB差分走线实例,详细说明了如何选择计算模型、填写参数并确定线宽线距。文章还提供了层叠设计资料和工厂常规阻抗表格作为参考,建议制板时标注需控阻抗的线路供板厂调整。最后简单提及了嘉立创阻抗计算工具作为备选方案。

weixin_50120208的博客 2024

手把手教你用内核远程call实现64位进程注入(附完整ShellCode示例)

本文深入探讨了在Windows 64位环境下,通过内核态直接操作线程TrapFrame结构实现进程注入的高级技术。文章提供了从驱动框架设计、用户态-内核态通信,到定位修改TrapFrame、编写Shellcode及执行环境恢复的完整实战指南,并附有详细的代码示例,为安全研究人员和开发者提供了绕过用户态检测、实现底层远程代码执行的新思路。

weixin_28396629的博客 344

Java反序列化和PHP反序列化的区别

反序列化存在的意义是为了数据传输,类是无法直接进行传输的。通过序列化后转换为字符串格式或者JSON格式进行传输。

来日可期的博客 2355

FlexSim:FlexSim软件介绍与安装

在开始安装FlexSim之前,首先需要从FlexSim官方网站下载安装包。FlexSim提供不同版本的软件,包括教育版、专业版等,确保选择适合您需求的版本。下载页面通常会列出系统要求,包括操作系统、处理器、内存和硬盘空间,确保您的计算机满足这些要求。访问FlexSim官方网站。导航至下载页面。选择适合您需求的FlexSim版本。点击下载按钮,开始下载安装包。在开始构建模型之前,首先需要明确模型的目标。模型目标是指导模型设计和分析的核心,它定义了你希望通过模型解决的问题或探索的系统行为。

kkchenjj的博客 5802

Java中的序列化和反序列化

目录 序列化和反序列化 JAVA WEB中的序列化和反序列化 对象序列化和反序列示例 序列化和反序列化 序列化 (Serialization):将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。 反序列化:从存储区中读取该数据,并将其还原为对象的过程,称为反序列化。 简单的说,序列化和反序列化就是: 把对象转换为字节序列的过程称为对象的序列化 把字节序列恢复为对象的过程称为对象的反序列化 对象序列化的用途: 把对象的字节序列永久地保

谢公子的博客 1592

虚拟机安装VMware Tools

单击虚拟机-->安装VMware Tool 安装之后会有一个VMware Tools硬盘,里面有VMware Tools.tar.gz的压缩包 按照提示解压它,然后执行vmware-install.pl安装VMware Tools 将安装包放到/tmp目录下。可以直接拽过去,也可以使用cp或者mv命令 进入tmp文件目录并解压此文件包 cd /tmp ...

afei001 620

【LAMMPS学习】四、运行 LAMMPS(2)命令行选项

本部分解释了在安装可执行文件或下载源代码并构建可执行文件后如何运行 LAMMPS。命令文档页面描述了输入脚本的结构以及它们可以包含的命令。

荷塘阅色 5242

Java——序列化和反序列化

文章目录什么是序列化和反序列化序列化和反序列化的使用如何保证反序列化后对象地址一致 什么是序列化和反序列化 序列化和反序列化一直都是一种很模糊的概念,关于理论有位大佬这么说到: 把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 参考博客:Java对象的序列化和反序列化 本篇博客对其不做过多的阐述,只是单纯的说明序列化和反序列化使用时需要注意的相关细节。 序列化和反序列化的使用 Java为了保证一个具有序列化和反序列化的能力,对其提供了一个接口java.io.S

专注写bug 1204

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java序列化和反序列化基础学习

(1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;(2)**序列化:**对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

dayouzi的博客 1411

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

什么是Java序列化和反序列化?

一、先来说说什么是序列化和反序列化? java对象序列化的意思就是将对象的状态转换成字节流,以后可以通过这些值在生成相同状态的对象,对象序列化就是对象持久化的一种实现方法,它是将对象的属性和方法转化为一种序列化的形式用于存储和传输,反序列化就是根据这些保存的信息重建对象的过程。 总之: 序列化就是将java对象转化为字节序列的过程 反序列化就是将字节序列转换为java对象的过程 二、那么我们为什么要进行序列化呢? 当我们两个进程进行远程...

立志欲坚不欲锐,成功在久不在速度 3412

JAVA序列化和反序列化

把 Java 对象转换成字节流(byte[]),以便存储到文件、数据库或通过网络传输。:把字节流还原回 Java 对象实例(通过类的构造/类信息重建对象状态)。Java 原生序列化机制基于(标记接口),通过和实现写/读对象。关键点:类如果实现,JVM 就可以把其实例序列化。用于版本兼容性检查(不同会导致默认序列化会把非transient成员字段写入字节流。开发者可以通过自定义序列化/反序列化行为 —— 这既是强大功能,也是危险来源(因为反序列化时这些方法会执行代码)。

rasssel的博客 1056

【Java基础面试题001】Java中序列化和反序列化是什么?

在Java中,序列化和反序列化是用于将对象的状态的重要机制。

lklalmq的博客 838

Java 基础之序列化和反序列化

如 JDK 内置的序列化框架、Fastjson、Hessian、Kryo 等,在序列化后的字节大小、序列化 / 反序列化耗时等方面表现不同。Java 序列化和反序列化是软件开发中的重要概念,在数据存储、网络通信和远程调用等场景中发挥着关键作用。总之,Java 序列化和反序列化在现代软件开发中发挥着至关重要的作用,它们使得数据的存储和传输变得简单和高效。总之,Java 序列化和反序列化在现代软件开发中不可或缺,但在使用过程中需注意各种问题,以确保程序的安全、稳定和高效运行。关键字等措施防御漏洞。

qq_25699299的博客 1323

java反序列化的原理_Java 序列化和反序列化的底层原理

序列化和反序列化序列化是通过某种算法将存储于内存中的对象转换成可以用于持久化存储或者通信的形式的过程反序列化是将这种被持久化存储或者通信的数据通过对应解析算法还原成对象的过程,它是序列化的逆向操作为什么需要序列化前端请求后端接口数据的时候,后端需要返回 JSON 数据,这就是后端将 Java 堆中的对象序列化为了 JSON 数据传给前端,前端可以根据自身需求直接使用或者将其反序列化为 JS 对象R...

weixin_36051235的博客 1694

Java中的序列化和反序列化原理

在Java中,序列化是指将对象转换成字节流的过程,可以将对象保存在硬盘或者通过网络进行传输。反序列化则指将字节流转换成对象的过程,可以从硬盘中读取序列化的对象或者接收网络传输的字节流并转换为对象。序列化和反序列化的主要目的是实现对象的持久化,即使程序结束或者网络连接断开,序列化的对象仍然可以被恢复为原始的对象。

小筱在线博客 1294
上一篇: Gitlab CI-CD自动化部署SpringBoot项目
下一篇: Docker方式安装Consul配置中心
ProgrammingWay
博客等级 码龄9年 58粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值