当前位置: 首页 > news >正文

面试系列 - 序列化和反序列化详解

Java 序列化是一种将对象转换为字节流的过程,可以将对象的状态保存到磁盘文件或通过网络传输。反序列化则是将字节流重新转换为对象的过程。Java 提供了一个强大的序列化框架,允许你在对象的持久化和网络通信中使用它。

一、Java 序列化的基本原理

Java 序列化的基本原理是将一个 Java 对象转换为一个字节序列,以便将其保存到磁盘上的文件或通过网络发送到其他地方。这个字节序列可以随后被反序列化为原始对象。

Java 序列化的主要实现是通过 java.io.Serializable 接口来实现的。只有实现了这个接口的类才能被序列化。该接口没有任何方法,它只是一个标识接口,用来表示一个类的实例可以被序列化。

要序列化一个对象,你可以使用 ObjectOutputStream 类,将对象写入输出流。要反序列化一个对象,可以使用 ObjectInputStream 类,从输入流中读取字节并重新构建对象。

以下是一个简单的 Java 序列化和反序列化的示例:

import java.io.*;class Student implements Serializable {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String toString() {return "Name: " + name + ", Age: " + age;}
}public class SerializationExample {public static void main(String[] args) {// 创建一个 Student 对象Student student = new Student("Alice", 25);// 序列化对象到文件try (FileOutputStream fileOut = new FileOutputStream("student.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut)) {out.writeObject(student);System.out.println("Object has been serialized");} catch (IOException e) {e.printStackTrace();}// 反序列化对象try (FileInputStream fileIn = new FileInputStream("student.ser");ObjectInputStream in = new ObjectInputStream(fileIn)) {Student deserializedStudent = (Student) in.readObject();System.out.println("Object has been deserialized");System.out.println(deserializedStudent);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

在这个示例中,我们首先创建一个 Student 类,并实现了 Serializable 接口。然后,我们创建一个 Student 对象,将其序列化到名为 "student.ser" 的文件中,并通过反序列化重新构建对象。

二、序列化版本UID

Java 对象在序列化时,会自动生成一个序列化版本UID(serialVersionUID),它是一个64位的哈希码,用于标识对象的版本。当对象被反序列化时,Java 会比较传入对象的版本UID和类中声明的版本UID是否匹配,如果不匹配,将抛出 InvalidClassException

你可以显式地声明版本UID,以确保对象在类结构变化时仍然可以正确反序列化。例如:

private static final long serialVersionUID = 123456789L;

三、注意事项和最佳实践

  • 序列化是 Java 中用于对象持久化的一种方式,但不适合所有情况。要慎重选择是否使用序列化,特别是在分布式系统中。

  • 被序列化的类必须实现 Serializable 接口,而且要小心处理敏感信息,如密码等,不要序列化敏感数据。

  • 在反序列化时,要确保类的版本和序列化时相同,否则可能会导致版本不匹配的问题。

  • 序列化和反序列化可能会对性能产生一定的影响,因此在高性能要求的场景中要小心使用。

四、常见序列化协议 

常见的序列化协议有很多,它们用于在不同的应用和平台之间序列化和反序列化数据。

  1. Java 序列化(Java Serialization): Java 标准库中的序列化机制,用于将 Java 对象序列化为字节流,以便在不同 Java 应用之间进行数据传输和持久化。这种序列化方式使用 java.io.Serializable 接口。

  2. JSON(JavaScript Object Notation): 一种轻量级的数据交换格式,易于阅读和编写。JSON 可以在不同的编程语言之间进行数据交换,广泛用于 Web 开发和 RESTful API。

  3. XML(eXtensible Markup Language): 一种通用的标记语言,用于将结构化数据序列化为文本格式。XML 也可用于不同编程语言之间的数据交换,尤其在企业级应用中广泛使用。

  4. Protocol Buffers(Protobuf): Google 开发的一种轻量级的二进制数据序列化协议,它具有高效的编解码性能和紧凑的数据表示。Protobuf 支持多种编程语言。

  5. Apache Avro: 一种数据序列化框架,支持多种编程语言。Avro 使用 JSON 格式来定义数据结构,并可以将数据序列化为二进制格式。

  6. Thrift: 由 Facebook 开发的一种跨语言的远程过程调用(RPC)框架,支持多种数据序列化格式,包括二进制、JSON 和 XML。

  7. MessagePack: 一种高效的二进制序列化格式,通常用于在不同平台之间传输数据。它比 JSON 和 XML 更紧凑,解析速度更快。

  8. CBOR(Concise Binary Object Representation): 一种二进制序列化格式,旨在与 JSON 兼容,但比 JSON 更紧凑和高效。

  9. BSON(Binary JSON): 一种二进制 JSON 格式,主要用于 MongoDB 数据库的存储和交换。

  10. Hessian 和 Burlap: 由 Caucho Technology 开发的一组二进制序列化协议,用于远程过程调用和数据交换。

这些序列化协议各有优点和适用场景,你可以根据项目的需求和技术栈来选择合适的协议。例如,如果需要高效的二进制序列化和跨语言支持,Protocol Buffers 或 MessagePack 可能是不错的选择;如果需要易读的数据交换格式,JSON 或 XML 可能更合适。

五、序列化协议对应于 TCP/IP 4 层模型

序列化协议通常不直接对应于 TCP/IP 4 层模型中的任何一层。TCP/IP 4 层模型包括以下层级:

  1. 应用层(Application Layer): 应用层协议负责定义应用程序之间的通信规则和数据交换格式。序列化协议通常在这一层中使用,以便将应用程序的数据序列化为可在网络上传输的格式。

  2. 传输层(Transport Layer): 传输层协议负责在网络上可靠地传输数据。TCP(传输控制协议)和UDP(用户数据报协议)是传输层协议的例子。序列化协议不属于传输层,但序列化后的数据可以通过传输层协议传输。

  3. 网络层(Network Layer): 网络层负责在不同网络之间路由数据包。IP(Internet Protocol)是网络层的核心协议。序列化协议通常不直接与网络层相关。

  4. 数据链路层(Data Link Layer): 数据链路层负责将数据帧从一个物理介质传输到另一个物理介质,通常与网络硬件相关。这一层与序列化协议无关。

序列化协议通常位于应用层,它定义了如何将应用程序中的数据序列化为可传输的格式,以及如何在接收端反序列化这些数据。然后,这些序列化后的数据可以使用传输层协议(如TCP或UDP)进行传输,以便在网络上进行数据交换。

六、serialVersionUID作用

serialVersionUID 是 Java 中用于序列化版本控制的一个特殊字段。它是一个静态常量,用于标识类的不同版本,以确保在反序列化过程中,序列化的类与反序列化的类具有兼容的版本。

serialVersionUID 的作用包括:

  1. 版本兼容性: 当类的结构发生变化(例如添加、删除或修改字段,或者改变继承关系)时,serialVersionUID 可以确保在反序列化时不会导致版本不匹配的问题。如果反序列化时发现版本不匹配,会抛出 InvalidClassException

  2. 允许反序列化旧版本: 如果你需要反序列化之前版本的对象,可以通过指定旧版本的 serialVersionUID 来实现。这允许你在升级应用程序时仍然能够处理旧版本的序列化数据。

  3. 避免不必要的异常: 如果没有明确指定 serialVersionUID,Java 将根据类的结构自动生成一个版本号。但是,如果类的结构发生了变化,自动生成的版本号可能会导致不匹配的异常。通过显式设置 serialVersionUID,可以避免这种情况。

七、如果有些字段不想进行序列化怎么办

如果你希望某些字段不参与序列化,你可以使用 transient 关键字来标记这些字段。被 transient 修饰的字段不会被序列化,它们在序列化过程中会被忽略。当对象被反序列化时,这些字段会被赋予默认值。

以下是示例:

import java.io.Serializable;public class MyClass implements Serializable {private String name;private transient int age; // age 字段不会被序列化public MyClass(String name, int age) {this.name = name;this.age = age;}// 其他成员变量和方法
}

在上面的示例中,age 字段被标记为 transient,这意味着在将 MyClass 对象序列化时,age 字段的值不会被包括在序列化数据中。当你反序列化 MyClass 对象时,age 字段会被赋予其默认值(0 对于 int 类型)。

使用 transient 关键字是一种常见的方式来控制哪些字段需要被序列化,哪些字段不需要。通常,不需要序列化的字段包括临时状态或不适合在序列化过程中传输的数据。例如,密码字段通常被标记为 transient,以确保它们不会在网络传输或持久化到磁盘时泄漏。

相关文章:

面试系列 - 序列化和反序列化详解

Java 序列化是一种将对象转换为字节流的过程,可以将对象的状态保存到磁盘文件或通过网络传输。反序列化则是将字节流重新转换为对象的过程。Java 提供了一个强大的序列化框架,允许你在对象的持久化和网络通信中使用它。 一、Java 序列化的基本原理 Jav…...

基于Elasticsearch + Fluentd + Kibana(EFK)搭建日志收集管理系统

目录 1、EFK简介 2、EFK框架 2.1、Fluentd系统架构 2.2、Elasticsearch系统架构 2.3、Kibana系统架构 3、Elasticsearch接口 4、EFK在虚拟机中安装步骤 4.1、安装elasticsearch 4.2、安装kibana 4.3、安装fluentd 4.4、进入kibana创建索引 5、Fluentd配置介绍 VC常…...

【Python小项目之Tkinter应用】解决Python的Pyinstaller将.py文件打包成.exe可执行文件后文件过大的问题

文章目录 前言1. 创建新项目![请添加图片描述](https://img-blog.csdnimg.cn/36dcadc85d864a08b93af78b9e79ff6d.jpeg)2.删除原项目中的全部文件3.将要打包的文件放入该项目目录下4.创建虚拟环境5.设置解释器为虚拟环境中的python解释器6.查看是否成功使用虚拟环境中的python解…...

Ab3d.DXEngine 6.0 Crack 2023

Ab3d.DXEngine 不是另一个游戏引擎(如Unity),它强迫您使用其游戏编辑器、其架构,并且需要许多技巧和窍门才能在标准 .Net 应用程序中使用。Ab3d.DXEngine 是一个新的渲染引擎,它是从头开始构建的,旨在用于标…...

Wireshark抓包常用指令

1.常用过滤规则 指定源地址: ip.src 10.0.1.123ip.src 10.0.1.123 && udphttp数据链路层:筛选mac地址为04:f9:38:ad:13:26的数据包----eth.src 04:f9:38:ad:13:26筛选源mac地址为04:f9:38:ad:13:26的数据包----eth.src 04:f9:38:ad:13:26网…...

Docker Swarm

Docker Swarm提供 Docker 容器集群服务,是 Docker 官方对容器云生态进行支持的核心方案。将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。 Swarm mode内置 kv 存储功能,提供了众多的新特性,比如&a…...

jupyter notebook安装和删除kernel的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

中级深入--day16

爬虫(Spider),反爬虫(Anti-Spider),反反爬虫(Anti-Anti-Spider) 之间恢宏壮阔的斗争... Day 1 小黄想要某站上所有的电影,写了标准的爬虫(基于HttpClient库),不断地遍历某站的电影列表页面,根据 Html 分析电影名字存进…...

【洛谷 P1031】[NOIP2002 提高组] 均分纸牌 题解(贪心)

[NOIP2002 提高组] 均分纸牌 题目描述 有 N N N 堆纸牌,编号分别为 1 , 2 , … , N 1,2,\ldots,N 1,2,…,N。每堆上有若干张,但纸牌总数必为 N N N 的倍数。可以在任一堆上取若干张纸牌,然后移动。 移牌规则为:在编号为 1 …...

E5071C是德科技网络分析仪

描述 E5071C网络分析仪提供同类产品中最高的RF性能和最快的速度,具有宽频率范围和多功能。E5071C是制造和R&D工程师评估频率范围高达20 GHz的RF元件和电路的理想解决方案。特点: 宽动态范围:测试端口的动态范围> 123 dB(典型值)快速测量速度:41毫秒全2端口…...

ViTPose+:迈向通用身体姿态估计的视觉Transformer基础模型 | 京东探索研究院

身体姿态估计旨在识别出给定图像中人或者动物实例身体的关键点,除了典型的身体骨骼关键点,还可以包括手、脚、脸部等关键点,是计算机视觉领域的基本任务之一。目前,视觉transformer已经在识别、检测、分割等多个视觉任务上展现出来…...

Android 播放mp3文件

1,在res/raw中加入mp3文件 2,实现播放类 import android.content.Context; import android.media.AudioManager; import android.media.SoundPool; import android.util.Log;import java.util.HashMap; import java.util.Map;public class UtilSound {pu…...

在OpenStack私有云上安装配置虚拟机

文章目录 零、学习目标一、登录大数据实训云二、创建网络三、创建路由四、添加接口五、创建端口六、添加安全组规则七、创建实例(一)实例规划(二)创建实例 - ied(三)创建实例 - master、slave1与slave2&…...

pyCharm远程DEBUG

第一步,添加一个远程机器的解释器 ssh 远程机器解释器添加, 我本地ssh有配置目标机器。 如果没配置,那就选着new server configuration 新增一个。 interpreter 指定远程机器python, (机器上有多个版本python里尤其要…...

微服务框架Go-kit

微服务框架Go-kit go kit简介第一个go kit应用go kit基本概念go kit Endpointsgo kit Endpoint 定义go kit Endpoint 函数签名go kit Endpoint 链式操作go kit Endpoint 请求和响应转换go kit Endpoint 中间件go kit Endpoint 错误处理go kit 传输层go kit HTTP 传输层go kit …...

《王道24数据结构》课后应用题——第三章 栈和队列

第三章 【3.1】 03、 假设以I和O分别表示入栈和出操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,可以操作的序列称为合法序列,否则称为非法序列。 如IOIIOIOO 和IIIOOIOO是合法的,而IOOIOIIO和II…...

查看linux开发板的CPU频率

1)查看CPU可设置的频率列表 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 2)查看CPU当前所使用的频率: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 3)设置CPU频率(最高…...

对象模型和this指针(个人学习笔记黑马学习)

1、成员变量和成员函数 #include <iostream> using namespace std; #include <string>//成员变量和成员函数分开存储class Person {int m_A;//非静态成员变量 属于类的对象上的static int m_B;//静态成员变量 不属于类的对象上void func() {} //非静态成员函数 不…...

SpringCloudAlibaba常用组件

SpringCloudAlibaba常用组件 微服务概念 1.1 单体、分布式、集群 单体 ⼀个系统业务量很⼩的时候所有的代码都放在⼀个项⽬中就好了&#xff0c;然后这个项⽬部署在⼀台服务器上就 好了。整个项⽬所有的服务都由这台服务器提供。这就是单机结构。 单体应⽤开发简单,部署测试…...

Shotcut for Mac:一款强大而易于使用的视频编辑器

随着数码相机的普及&#xff0c;视频编辑已成为我们日常生活的一部分。对于许多专业和非专业用户来说&#xff0c;找到一个易于使用且功能强大的视频编辑器是至关重要的。今天&#xff0c;我们将向您介绍Shotcut——一款专为Mac用户设计的强大视频编辑器。 什么是Shotcut&…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...