Java序列化、反序列化-为什么要使用序列化?Serializable接口的作用?

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

  • 把对象转换成字节序列
  • 把字节序列恢复成对象

结合OSI七层协议模型,序列化和反序列化是在那一层做的?

在OSI七层模型中,序列化工作的层级是表示层。这一层的主要功能包括把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象。

为什么要使用序列化?

序列化的作用是将对象转换为可以存储或传输形式的过程,这样对象可以存储在内存或文件中(内存或文件实际上是以字节为单位的),我们要转换成机器能够认识的单位。比方说我们需要把一个对象传输到另一台机器

网络传输,跨机器,要转换成机器能识别的格式,反之

Serializable接口的作用

做标记,实现Serializable接口的类表示可以序列化,告诉程序实现了它的对象是可以被序列化的。如果对某个没有实现Serializable接口的类直接序列化将会报”NotSerializableException“错误。

这个时候有些人就会想:当对象中的某些信息,比方说密码或身份证,我不想暴露有没有什么办法?当然JDK已经给我们想到了这些问题,为了保障数据的安全性,当实现serialVersional接口实现序列化的时候可以使用transient或static关键字修饰某个字段,被修饰的字段就不会被序列化反序列时也不会被持久化和恢复,会被置成默认值

//因为序列化保存的是对象的状态,而 static 修饰的字段属于类的状态,因此可以证明序列化并
//不保存 static 修饰的字段。
public static Long cardId;// transient临时修饰成员,阻止字段被序列化
//当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复,会被置成类型默认值
private transient String password;

注意:

普通对象序列化和反序列化返回的是两个不同的对象

枚举类型序列化的对象是static final的,不会回收,所以反序列化回来的对象和原来的对象是同一个

序列化和反序列化的方式有哪些?

  1. JDK自带序列化方式
  2. Kryo

JDK自带序列化方式

Student类
package org.example.SerializableTest;import lombok.Data;import java.io.Serializable;@Data
public class Student implements Serializable {private static final long serialVersionUID = 1L;public Student(String name,Integer age,Integer score,Integer studentId,String password){this.name=name;this.age=age;this.score=score;this.studentId=studentId;this.password=password;}private String name;private Integer age;private Integer score;private Integer studentId;// transient瞬态修饰成员,不会被序列化//当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复,会被置成类型默认值private transient String password;
}

序列化:
Student student = new Student("唐三", 18, 100, 001, "123456");try {FileOutputStream fos = new FileOutputStream("dlm.txt");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(student);oos.close();} catch (IOException e) {e.printStackTrace();
}

反序列化:

通过输出文件中的对象我们可以发现用transient修饰的password字段被隐藏了,保证了信息的安全

在Student类中不知道大家有没有发现serialVersionUID这个字段,这个字段的作用用来验证版本的,对版本进行表示。在序列化的时候会记录将serialVersionUID

在反序列化的时候将serialVersionUID和本地实体类的serialVersionUID进行比较,如果一致则可以反序列化,否则则说明序列化版本不一致

serialVersionUID默认是“1L”,可以自动生成

Kryo

是一个支持序列化/反序列化的工具

KryoStudent类

package org.example.SerializableTest;import lombok.Data;@Data
class KryoStudent {public KryoStudent() {}public KryoStudent(String name, Integer age, Integer score, Integer studentId, String password) {this.name = name;this.age = age;this.score = score;this.studentId = studentId;this.password = password;}private String name;private Integer age;private Integer score;private Integer studentId;private transient String password;@Overridepublic String toString() {return "KryoStudent{" +"name='" + name + '\'' +", age=" + age +", score=" + score +", studentId=" + studentId +", password='" + password + '\'' +'}';}
}
package org.example.SerializableTest;import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.objenesis.strategy.StdInstantiatorStrategy;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;public class KryoDemo {public static void main(String[] args) throws FileNotFoundException {//创建一个 Kryo 对象Kryo kryo = new Kryo();//将对象进行注册kryo.register(KryoStudent.class);KryoStudent object = new KryoStudent("唐三", 18, 100, 001, "123456");//序列化Output output = new Output(new FileOutputStream("dlm.txt"));//将 Java 对象序列化为二进制流kryo.writeObject(output, object);output.close();Input input = new Input(new FileInputStream("dlm.txt"));//将二进制流反序列化为 Java 对象KryoStudent object2 = kryo.readObject(input, KryoStudent.class);System.out.println(object2);input.close();}//反序列化public void setSerializableObjectStudent() throws FileNotFoundException {Output output = new Output(new FileOutputStream("dlm.txt"));Kryo kryo = new Kryo();kryo.setReferences(false);kryo.setRegistrationRequired(false);kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());kryo.register(KryoStudent.class);}
}
Kryo方式有什么缺点吗?
  1. 不是线程安全的,每个线程都有自己的Kryo对象、输入和输出实例
  2. 只支持Java实现


既然JDK和Kryo都可以进行序列化和反序列化,那分别用JDK和Kryo提供的序列化和反序列化方式对10000个对象进行转换,从时间上我们来看一下它的性能

JDK和Kryo性能对比

Student类

import lombok.Data;import java.io.Serializable;@Data
public class Student implements Serializable {public Student(String name, Integer age, Integer score, Integer studentId, String password){this.name=name;this.age=age;this.score=score;this.studentId=studentId;this.password=password;}private String name;private Integer age;private Integer score;private Integer studentId;// transient瞬态修饰成员,不会被序列化private transient String password;
}

KryoStudent类

import lombok.Data;@Data
class KryoStudent {//Kryo不支持包含无参构造器类的反序列化,所以需要把无参构造器显示出来。public KryoStudent() {}public KryoStudent(String name, Integer age, Integer score, Integer studentId, String password) {this.name = name;this.age = age;this.score = score;this.studentId = studentId;this.password = password;}private String name;private Integer age;private Integer score;private Integer studentId;private transient String password;@Overridepublic String toString() {return "KryoStudent{" +"name='" + name + '\'' +", age=" + age +", score=" + score +", studentId=" + studentId +", password='" + password + '\'' +'}';}
}

JDK序列化和反序列化

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.junit.Test;import java.io.*;
import java.util.ArrayList;public class test5 {//序列化@Testpublic void test1() throws Exception {long time = System.currentTimeMillis();ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dlm.txt"));for (int i = 0; i < 10000; i++) {oos.writeObject(new Student("唐三", 18, 100, i, "123456"));}oos.close();System.out.println("JDK序列化消耗的时间" + (System.currentTimeMillis() - time));}//反序列化@Testpublic void test2() throws Exception {long time = System.currentTimeMillis();ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dlm.txt"));Student student = null;try {while (null != (student = (Student) ois.readObject())) {}} catch (EOFException e) {}System.out.println("JDK反序列化消耗的时间" + (System.currentTimeMillis() - time));}
}

Kryo序列化和反序列化

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.junit.Test;import java.io.*;
import java.util.ArrayList;public class test5 {//序列化@Testpublic void test1() throws Exception {long time = System.currentTimeMillis();Kryo kryo = new Kryo();//将对象进行注册kryo.register(KryoStudent.class);Output output = new Output(new FileOutputStream("dlm.txt"));//存储10000个对象for (int i = 0; i < 10000; i++) {kryo.writeObject(output, new KryoStudent("唐三", 18, 100, i, "123456"));}output.close();System.out.println("Kryo序列化消耗的时间" + (System.currentTimeMillis() - time));}//反序列化@Testpublic void test2() throws Exception {long time = System.currentTimeMillis();Kryo kryo = new Kryo();kryo.register(KryoStudent.class);Input input = new Input(new FileInputStream("dlm.txt"));KryoStudent student = null;//反序列化文件中的对象try {while (null != (student = kryo.readObject(input, KryoStudent.class))) {}} catch (KryoException e) {}input.close();System.out.println("Kryo反序列化消耗的时间" + (System.currentTimeMillis() - time));}
}

结果为:

从输出结果上我们发现时间上有很大的不同,Kryo序列化和反序列化相比于JDK都快很多,那为什么会产生这样的结果呢?

  1. Kryo依赖于字节码生成机制(底层使用了ASM库)
  2. Kryo序列化时,只将对象的信息、对象属性值的信息等进行序列化,没有将类field的描述信息进行序列化,这样就比JDK自己的序列化结果要小很多,而且速度肯定更快。
  3. Kryo序列化出的结果是其自定义的、独有的一种格式,因此像redis这样可以存储二进制数据的存储引擎可以直接将Kryo序列化出来的数据存进去也可以选择转换成String的形式存储在其他存储引擎中(性能有损耗)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue中用v-html根据后端返回结果设置样式

一、问题 1》今日遇到一个需求&#xff0c;是一个表格列返回状态status&#xff0c;并拥有多种不同颜色。 2》平日里见到的基本都是返回01234......前端用插槽放进去&#xff0c;根据数字去判断显示字段以及设置不同样式&#xff0c;今天看到的是后端直接返回一个字符串&#…

面试经典150题(27-28)

leetcode 150道题 计划花两个月时候刷完&#xff0c;今天&#xff08;第十三天&#xff09;完成了2道(27-28)150&#xff1a; 今天这两道是真的汗流浃背&#xff01;&#xff01;&#xff01; 27.&#xff08;209. 长度最小的子数组&#xff09;题目描述&#xff1a; 给定一…

SpringBoot3 Web开发新特性(Problemdetails、函数式Web)

目录 1. Problemdetails2. 函数式Web2.1 场景2.2 主要逻辑2.3 核心对象2.4 示例程序 1. Problemdetails 错误信息返回新格式 package org.springframework.boot.autoconfigure.web.servlet; ......省略部分...... public class WebMvcAutoConfiguration {......省略部分.....…

Leetcode 2967. Minimum Cost to Make Array Equalindromic

Leetcode 2967. Minimum Cost to Make Array Equalindromic 1. 解题思路2. 代码实现 题目链接&#xff1a;2967. Minimum Cost to Make Array Equalindromic 1. 解题思路 这一题其实我的思路有点笨&#xff0c;多少有点暴力求解的意思。 显然&#xff0c;如果我们给出全部的…

PCL 点云半径查找

目录 一、 算法概述二、代码实现三、测试示例一、 算法概述 适用:根据已知点坐标,在点云中搜索其指定半径范围内的所有点云。 二、代码实现 #include <iostream> #include <vector> #include <

如何搭建企业管理系统Odoo并远程访问管理界面【内网穿透】

文章目录 前言1. 下载安装Odoo&#xff1a;2. 实现公网访问Odoo本地系统&#xff1a;3. 固定域名访问Odoo本地系统 前言 Odoo是全球流行的开源企业管理套件&#xff0c;是一个一站式全功能ERP及电商平台。 开源性质&#xff1a;Odoo是一个开源的ERP软件&#xff0c;这意味着企…

【贪心算法】【中位贪心】LeetCode:100123.执行操作使频率分数最大

涉及知识点 双指针 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 贪心算法 题目 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 你可以对数组执行 至多 k 次操作&#xff1a; 从数组中选择一个下标 i &#xff0c;将 nums[i] …

【云原生之Docker实战】Docker环境下部署群晖DSM系统(详细教程)

【云原生之Docker实战】Docker环境下部署群晖DSM系统(详细教程) 一、Virtual DSM介绍2.1 Virtual DSM特点二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、环境准备工作4.1 检查c…

STL技术概述与入门

STL技术概述与入门 STL介绍STL六大组件初识容器算法迭代器1. vector存放内置数据类型2. Vector存放自定义数据类型3. Vector容器的嵌套 ✨ 总结 参考博文1&#xff1a;STL技术——STL概述和入门 参考博文2&#xff1a;&#xff1c;C&#xff1e;初识STL —— 标准模板库 STL介…

Android开发中pcm格式的音频转换为wav格式之二

上篇Android开发中pcm格式的音频转换为wav格式的工具类-CSDN博客文章讲解了pcm格式的音频转换为wav格式&#xff0c;这篇文章主要讲解怎么使用&#xff1a; 我们先来说明一下怎么播放一个wav文件 /*** 播放一个wav文件*/public static void playWav(String filePath){File wav…

SpringBoot配置mysql加密之Druid方式

一、导入Druid依赖 <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.22</version> </dependency>二、生成密文 方式1. 找到存放druid jar包的目录 1-1、在目录…

【Proteus仿真】【Arduino单片机】电子称重秤

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使LCD1602液晶&#xff0c;矩阵按键、蜂鸣器、HX711称重模块等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示HX711称重模块检测重量…

kafka设置消费者组

安装部署后 consumer.properties group.idtest-group 单机测试&#xff0c;自己开俩窗口&#xff0c;一个测试消费者&#xff0c;一个测试生产者&#xff08;创建消息那步&#xff09; 创建主题 bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replica…

人工智能与自动驾驶:智能出行时代的未来之路

一、前言 首先&#xff0c;我们先来说下什么是人工智能&#xff0c;人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使计算机系统能够模拟、仿真人类智能的技术和科学领域。它涉及构建智能代理&#xff0c;使其能够感知环境、理解和…

怎么检测DC-DC电源模块稳定性?电源测试系统测试有什么优势?

DC-DC电源模块稳定性测试 稳定性是衡量DC电源模块的重要指标&#xff0c;电源模块的稳定性直接影响着电源产品和设备的工作稳定性。DC-DC电源模块的稳定性&#xff0c;可以通过检测输出电压、输出电流、负载、波形、效率等参数来评估。 1. 静态测试方法 静态测试是通过直流电压…

【DataSophon】大数据服务组件之Flink升级

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&am…

性能测试QPS+TPS+事务基础知识分析

事务 就是用户某一步或几步操作的集合。不过&#xff0c;我们要保证它有一个完整意义。比如用户对某一个页面的一次请求&#xff0c;用户对某系统的一次登录&#xff0c;淘宝用户对商品的一次确认支付过程。这些我们都可以看作一个事务。那么如何衡量服务器对事务的处理能力。…

部署智能合约以及 javascript 调用合约函数(Web3项目二实战之三)

在上一篇 智能合约是Web3项目的核心要务(Web3项目二实战之二) ,我们已然为项目编写了智能合约,在攥写完智能合约后,该项目将完成了一大部分,剩下无非就是用户界面交互的内容。 然而,在码完了智能合约代码后,起着承前启后关键性的便是,前端界面与智能合约的交互。 智能…

ansible远程操作主机功能(1)

自动化运维&#xff08;playbook剧本yaml&#xff09; 是基于Python开发的配置管理和应用部署工具。自动化运维中&#xff0c;现在是异军突起。 Ansible能批量配置&#xff0c;部署&#xff0c;管理上千台主机&#xff0c;类似于Xshell的一键输入的工具&#xff0c;不需要每次…

【IOS开发】传感器 SensorKit

资源 官方文档 https://developer.apple.com/search/?qmotion%20graph&typeDocumentation SensorKit 使应用程序能够访问选定的原始数据或系统从传感器处理的指标。 步骤信息加速度计或旋转速率数据用户手腕上手表的配置物理环境中的环境光有关用户日常通勤或旅行的详细…