Java序列化与数据传输

article/2025/9/14 3:48:51

1)什么是序列化

① 序列化:Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

堆内存中的java对象数据,通过某种方式把该对象存储到磁盘文件中,或者传递给其他网络节点(网络传输)。

对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。核心作用是对象状态的保存与重建。

② 反序列化:将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。

把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。

客户端从文件中或网络上获得序列化后的对象字节流,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

③ 什么场景下会使用到序列化:

暂存大对象;

Java对象需要持久化的时候;

需要在网络,例如socket中传输Java对象。因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送出去之前需要先序列化成二进制数据,在接收端读到二进制数据之后反序列化成Java对象;

跨虚拟机通信;

2)实现Java序列化

ObjectInputStreamObjectOutputStream 是高层次的数据流,包含了序列化和反序列化的方法。

ObjectOutputStream 类包含很多写方法来写各种数据类型,但是一个特别的方法例外:

public final void writeObject(Object x) throws IOException

上面的方法序列化一个对象,并将它发送到输出流。相似的 ObjectInputStream 类包含如下反序列化一个对象的方法:

public final Object readObject() throws IOException, ClassNotFoundException                 

该方法从流中取出下一个对象,并将对象反序列化。它的返回值为Object,因此,你需要将它转换成合适的数据类型。

ObjectOutputStream - writeObject - 序列化一个对象,并将它发送到输出流。

ObjectInputStream  - readObject - 从输入流中取出下一个对象,并将对象反序列化。

① 实现Serializable接口;

public class Employee implements java.io.Serializable
{private static final long serialVersionUID = 1L;private String name;private String address;public transient int SSN;private int number;public void mailCheck(){System.out.println("Mailing a check to " + name + " " + address);}
}

一个类的对象要想序列化成功,必须满足两个条件:

该类必须实现 java.io.Serializable 接口。

该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。

② 进行序列化;

public class SerializeDemo
{public static void main(String [] args){Employee e = new Employee();e.name = "Reyan Ali";e.address = "Phokka Kuan, Ambehta Peer";e.SSN = 11122333;e.number = 101;try{FileOutputStream fileOut =new FileOutputStream("/tmp/employee.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(e);out.close();fileOut.close();System.out.printf("Serialized data is saved in /tmp/employee.ser");}catch(IOException i){i.printStackTrace();}}
}

③ 进行反序列化;

public class DeserializeDemo
{public static void main(String [] args){Employee e = null;try{FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");ObjectInputStream in = new ObjectInputStream(fileIn);e = (Employee) in.readObject();in.close();fileIn.close();}catch(IOException i){i.printStackTrace();return;}catch(ClassNotFoundException c){System.out.println("Employee class not found");c.printStackTrace();return;}}
}

readObject() 方法中的 try/catch代码块尝试捕获 ClassNotFoundException 异常。对于 JVM 可以反序列化对象,它必须是能够找到字节码的类。如果JVM在反序列化对象的过程中找不到该类,则抛出一个 ClassNotFoundException 异常。

序列化流程:

 1)定义一个类,实现Serializable接口;

 2)在程序代码中创建对象后,创建对象输出流ObjectOutputStream对象并在构造参数中指定流的输出目标(比如一个文件),通过objectOutputStream.writeObject(obj)把对象序列化并输出到流目标处;

 3)在需要提取对象处:创建对象输入流ObjectInputStream对象并在构造参数中指定流的来源,然后通过readObject()方法获取对象,并通过强制类型转换赋值给类对象引用。

3)序列化过程中几个需要注意的点

① 序列化ID,我们在进行序列化时,加了一个serialVersionUID字段,这便是序列化ID;

 private static final long serialVersionUID = 1L;

虚拟机是否允许对象反序列化,不是取决于该对象所属类路径和功能代码是否与虚拟机加载的类一致,而是主要取决于对象所属类与虚拟机加载的该类的序列化 ID 是否一致

Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

② 静态变量和transient关键字修饰的变量不能被序列化;

序列化时并不保存静态变量,这其实比较容易理解,序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。transient作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient变量的值设为初始值,如int型的是0。比如上面例子中SSN属性值反序列化后为0.

③ 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

4)序列化原理

① 序列化算法会按步骤执行以下事情:

  1)当前类描述的元数据输出为字节序列;【类定义描述、类中属性定义描述】

  2)超类描述输出为字节序列;【如果超类还有超类,则依次递归,直至没有超类】

  3)从最顶层超类往下,依次输出各类属性值描述,直至当前类对象属性值。

  即:从下到上描述类定义,从上往下输出属性值。

② 为什么Java序列化要实现Serializable接口:

package java.io;
public interface Serializable {
}

这是一个空接口,为什么要设计为空?总的就是说安全性问题,假如没有一个接口(即没有Serializable来标记是否可以序列化),让所有对象都可以序列化。那么所有对象通过序列化存储到硬盘上后,都可以在序列化得到的文件中看到属性对应的值(后面将会通过代码展示)。所以最后为了安全性(即不让一些对象中私有属性的值被外露),不能让所有对象都可以序列化。要让用户自己来选择是否可以序列化,因此需要一个接口来标记该类是否可序列化。

5)Serializable和Parcelable的区别和使用

Java 提供了 Serializable 接口,而 Android 提供特有的 Parcelable 接口。

Seralizable相对Parcelable而言,好处就是非常简单,只需对需要序列化的类class执行就可以,不需要手动去处理序列化和反序列化的过程,但是Serializable 在序列化和反序列化过程中大量使用了反射,效率较低,也因此其过程会产生的大量的内存碎片

Parcelable是Android特有的序列化API,它的出现是为了解决Serializable在序列化的过程中消耗资源严重的问题,但是因为本身使用需要手动处理序列化和反序列化过程,会与具体的代码绑定,使用较为繁琐,一般只获取内存数据的时候使用。

二者效率及选择

Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为Android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化。

6)常见的序列化技术

① Java 序列化

优点:java语言本省提供,使用比较方面和简单; 

缺点:不支持跨语言处理、性能相对不是很好,序列化以后产生的数据相对较大;

② XML序列化

XML序列化的好处在于可读性好,方便阅读和调试。但是序列化以后的字节码文件比较大,而且效率不高,适应于对性能不高,而且QPS较低的企业级内部系统之间的数据交换的场景,同时XML又具有语言无关性,所以还可以用于异构系统之间的数据交换和协议。

解析方式:Pull解析和SAX解析;笔者之前的文章《SVG解析》这里面就使用了Pull解析的方式,去解析一份SVG(XML)文件,效率可以保证。

③ JSON序列化

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于XML来说,JSON的字节流较小,在网络传输上更省流量,而且可读性也尚可。现在JSON数据格式的运用是最普遍的。

解析方式:官方提供了JSONObject,也可以使用谷歌的GSON,阿里的FastJSON,美团的MSON等更加优秀的转码工具。

 

参考文章:

《序列化原理(一):从源码理解Serializable》

《java序列化详解》

《Java序列化,看这篇就够了》

《Parcelable 和 Serializable的区别和使用》

 

借着博文记录近期一个Cmake的编译问题::一个项目有段时间没有运行,后续忽然出现下面的问题,

java.io.FileNotFoundException: D:\Work_project\Series_X\Artist Cam Editor\libraries\PixaToon-master\app\.externalNativeBuild\cmake\release\arm64-v8a\android_gradle_build.json

这个文件用来被Android Gradle Plugin中的externalNativeBuild任务解析,将构建命令解析出来,然后编译C/C++代码,最后产生目标so文件。

解决方法:"Build->Refresh linked C++ projects

 

 

 

 

 


http://chatgpt.dhexx.cn/article/Wf8dlQfE.shtml

相关文章

java序列化的作用

1.java序列化需要实现Serializaible接口或者Externalizable接口 2.java实现序列化的作用: 1.方便在远程调用时对象的解码与编码,就像new对象之间直接调用,不需要像传输对象之间像JSON转换一样转来转去 2.序列化的能力:为了在程序中能直接以对象的形式进…

Java序列化与反序列化

参考链接: Java 序列化与反序列化_Jacks丶的博客-CSDN博客_java反序列化 1 序列化与反序列化的概念 Java 序列化是指:将对象转化成一个字节序列(二进制数据)的过程。 将序列化对象写入文件之后,可以从文件中读取出来,并且对它…

Java序列化

一、什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程。 我们都知道,在进行浏览器访问的时候,我们看到的文本、图片、音频、视频等都是通…

【JAVA基础】java基础之-序列化详解

写在前面的话 脑子是个好东西,可惜的是一直没有搞懂脑子的内存删除机制是什么,所以啊,入行多年,零零散散的文章看了无数,却总是学习了很多也忘了很多。 痛定思痛的我决定从今天开始系统的梳理下知识架构,记…

JAVA的序列化

絮叨 Java序列化其实这个用的多不多,我觉得看公司的技术栈吧,如果用的是cloud那套,估计接触的会少点,但是也不是说没有,如果是dubbo那套的话,就多点,上次我们说Netty的编码解码的时候说到了谷歌…

MySQL卸载重新安装会遇到的问题及解决方式

好家伙,全踩雷了: 一.使用cd命令无法进入到其他盘符? 解决:在cd后加/d,两者之间用空格隔开 二.初始化时没有给出密码? 解决:仔细检查my.ini配置文件中的配置命令,一般是配置命令写错…

如何将MySQL卸载干净?

前言 前几天不知道什么情况电脑被莫名下载了MySQL8.0版本导致与本机的MySQL5.0版本冲突,导致MySQL无法正常运行,后来因为没有卸载干净MySQL导致一直下载不成功,导致我晚上失眠,现在让我们进入正题,看看如何将他卸载干…

【通关MySQL】Win11如何将MySQL卸载干净?

✨哈喽,进来的小伙伴们,你们好耶!✨ 🚀🚀系列专栏:【通关MySQL】 ✈️✈️本篇内容: MySQL如何卸载干净? ⛵⛵作者简介:一名双非本科大三在读的科班Java编程小白,道阻且长&#xff…

如何能将mysql卸载干净

本篇文章介绍一下如何干净卸载mysql。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 第七步出现找不到相应的文件夹。第七步:路径是C:\Users\你的用户名字\AppData\Roaming\MySQL 有可能是隐藏的,需要显示隐藏…

如何将mysql卸载干净

一、在控制面板中卸载mysql软件 二、卸载过后删除C:\Program Files (x86)\MySQL该目录下剩余了所有文件,把mysql文件夹也删了 三、windowsR运行“regedit”文件,打开注册表 四、删除注册表:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Service…

MySQL卸载安装

目录 MySQL卸载安装 1. MySQL卸载(8.0版本) 1.1停止MySQL服务 1.2 卸载MySQL相关组件 1.3删除MySQL安装目录 1.4删除MySQL数据目录 1.5 删除MySQL注册表信息(重要) 2. MySQL安装(5.7.24版本) 2.1安装…

mysql卸载不_mysql卸载不干净解决方法

一、在控制面板中卸载mysql软件,此时mysql没有卸载干净。 二、卸载过后删除C:Program Files (x86)MySQL该目录下剩余了所有文件,把mysql文件夹也删了 三、windowsR运行“regedit”文件,打开注册表 四、删除注册表:HKEY_LOCAL_MACH…

MySQL的卸载与安装(附管理工具Navicat SQLyog)

本文MySQL为5.1.51版本,附全文所需文件压缩包(百度云 提取码:8778),其中SQLyog和Navicat为MySQL的图形化工具,任选其一安装即可(建议Navicat) 1.MySQL卸载 如果之前没有安装过MySQ…

【 Windows、Mac 】Mysql 卸载、安装

文章目录 Windows Mysql 卸载、安装一、彻底卸载mysql二、安装mysql 5.7三、安装 mysql 8四、MySql服务开机自启动失败 Mac 安装 mysql一、下载对应mysql版本二、安装三、重置密码 Windows Mysql 卸载、安装 一、彻底卸载mysql 1、关闭 MySql 服务。 2、在控制面板卸载mysq…

MySQL卸载、安装与使用

一、MySQL卸载 1.关闭服务 点击win,输入服务,找到MySQL的服务,右击停止该服务 2.删除服务 点击win,输入cmd,选择管理员身份运行。打开cmd,输入sc delete mysql 3删除配置的MySQL环境变量 MySQLHOME和…

MySQL卸载不干净问题

解决MySQL卸载不干净或安装的时候安装不成功,输入密码一直检查不通过问题 MySQL卸载不干净,之后安装就会遇到很多问题,我也遇到了这种情况,裝了好久,一到这里就会有问题,尝试卸载了很多次然后在从新裝&…

mysql卸载详细教程

完整卸载MySQL数据库 1、关掉mysql服务 直接搜索服务或者右键“我的电脑”,选择“管理”,打开计算机管理,选择“服务”右键MySQL服务,选择“停止” 2、 卸载mysql程序 开始菜单->控制面板->程序和功能 3、 删除计算机上…

免装版mysql卸载

免装版mysql卸载: 1.停止mysql服务:以管理员身份打开cmd执行:net stop mysql 2.删除Mysql的注册表 winr 输入regedit打开注册表: 3.管理员cmd执行:mysqld -remove mysql 4.删除mysql之前的安装包:

MySQL卸载与安装

目录 1.MySQL卸载2.MySQL安装2.1获取mysql.zip2.1.1百度网盘链接2.1.2官网获取 2.2解压到自己想要安装的目录2.3初始化 MySQL2.4安装 MySQL 服务2.5修改登录密码2.6配置环境变量2.7其他问题2.7.1重置 MySQL 系统2.7.2忘记密码2.7.3版本切换2.7.4编码和 my.ini 设置2.7.5修改密码…

MySQL卸载

文章目录 将现有MySQL服务关闭(必做)确定自己MySQL的安装位置(辅助工作)方法1:适用于之前成功安装MySQL并完成环境变量配置的情况方法2:暴力搜索-适用于之前修改过安装位置的情况 在系统中卸载MySQL&#x…