详细聊聊 Java序列化和反序列化的作用
1、序列化和反序列化是什么?
如果你看过某些类的源码或者公司的项目,有一些类是实现 Serializable 接口,同时还要显示指定 serialVersionUID 的值。
例如String类:
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];/** Cache the hash code for the string */private int hash; // Default to 0/** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -6849794470754667710L;
先来解释一下这两个概念:
- 序列化:把对象转换为字节序列的过程称为对象的序列化.
- 反序列化:把字节序列恢复为对象的过程称为对象的反序列化.
太复杂了?
再简单点说:
序列化是指把一个Java对象变成二进制内容,本质上就是一个byte[]数组。
为什么要把Java对象序列化呢?
因为序列化后可以把byte[]保存到文件中,或者把byte[]通过网络传输到远程,这样,就相当于把Java对象存储到文件或者通过网络传输出去了。
有序列化,就有反序列化,即把一个二进制内容(也就是byte[]数组)变回Java对象。有了反序列化,保存到文件中的byte[]数组又可以“变回”Java对象,或者从网络上读取byte[]并把它“变回”Java对象。
2、序列化和反序列化的例子
public class SerializableTest {public static void main(String[] args) throws IOException, ClassNotFoundException {serializeStudent();deserializeStudent();}//序列化static void serializeStudent() throws IOException, ClassNotFoundException {FileOutputStream fos = new FileOutputStream("F:\\HaC.txt");ObjectOutputStream oos = new ObjectOutputStream(fos);Student student1 = new Student("HaC", "HelloCoder", 30);oos.writeObject(student1);oos.flush();System.out.println("Student 对象序列化成功!");oos.close();}static void deserializeStudent() throws IOException, ClassNotFoundException {//反序列化FileInputStream fis = new FileInputStream("F:\\HaC.txt");ObjectInputStream ois = new ObjectInputStream(fis);Student student2 = (Student) ois.readObject();System.out.println(student2.getUserName() + " " +student2.getPassword() + " " + student2.getYear());System.out.println("Student 对象反序列化成功!");}
}
@Data
@AllArgsConstructor
class Student implements Serializable{private static final long serialVersionUID = 3608451818006447637L;private String userName;private String password;private String year;//省略get、set
}
可以看到生成了一个打开是乱码的二进制文件:
其实这个例子就是序列化和反序列化的一个小过程,JVM通过序列化把对象写到文件,再通过反序列化从文件中读取数据,把数据转成一个对象。
看到控制台输出也是正常的:
Student 对象序列化成功!
HaC HelloCoder 30
Student 对象反序列化成功!
IDEA可以设置生成 serialVersionUID:
然后双击选中你的类,按下 Alt + Enter
:
作用
所以序列化和反序列化的作用是:
1、把对象转成JSON、xml 的时候,往往这些接口、方法 都实现了序列化,因为网络传输也是一个二进制的过程,需要进行转换
所以只要我们对内存中的对象进行持久化或网络传输, 这个时候都需要序列化和反序列化.
2、还有一个作用就是把对象的字节序列永久地保存到硬盘上 ,比如通过mybatis可持久化到MySQL,也是实现了序列化的。
比如:
<insert id="insertUser" parameterType="org.yudianxx.bean.User">INSERT INTO user(name, age) VALUES (#{name}, #{age})
</insert>
实际上我们并不是将整个对象持久化到数据库中, 而是将对象中的属性持久化到数据库中, 而这些属性都是实现了 Serializable 接口的基本属性。
3、为什么要实现 Serializable 接口还要指定serialVersionUID的值?
在 Java 中实现了 Serializable 接口后, JVM 会在底层帮我们实现序列化和反序列化,如果你实现该接口,你也可以自己自定义一个,就是有点复杂,这里不展开。
如果不显示指定 serialVersionUID, JVM 在序列化时会根据属性自动生成一个 serialVersionUID, 然后与属性一起序列化,再进行持久化或网络传输。
在反序列化时,JVM 会再根据属性自动生成一个新版 serialVersionUID,然后将这个新版 serialVersionUID 与序列化时生成的旧版 serialVersionUID 进行比较,如果相同则反序列化成功, 否则报错.
如果显示指定了 serialVersionUID, JVM 在序列化和反序列化时仍然都会生成一个 serialVersionUID, 但值为我们显示指定的值,这样在反序列化时新旧版本的 serialVersionUID 就一致了.
接上面的例子,我不生成serialVersionUID,反序列化也是没有问题的,但如果我指定了不一致的serialVersionUID ,或者加了新的属性:
class Student implements Serializable {// private static final long serialVersionUID = 1L;private String userName;private String password;private int year ;private int age;
再调用deserializeStudent()
反序列化方法时就会报错:
Exception in thread "main" java.io.InvalidClassException: com.yudianxx.basic.序列化.Student; local class incompatible: stream classdesc serialVersionUID = -2548470143096162701, local class serialVersionUID = -9192788448472055372
可以看到有一个默认的serialVersionUID
。
还有一种情况就是,假如你不实现Serializable
接口,在反序列化的时候也是会报错的:
class Student {private String userName;private String password;private int year ;
}
报错NotSerializableException
:
Exception in thread "main" java.io.NotSerializableException: com.yudianxx.basic.序列化.Student
通过这个例子你就大概知道,反序列化是和类和属性有关,就像秘钥和公钥一样,只有正确的serialVersionUID
和类匹配,才能反序列化。
3、序列化的其他特性
1、static 属性不会被序列化
2、transient 修饰的属性,也不会被序列化
当某个字段被声明为transient
后,默认序列化机制就会忽略该字段
这里我举个例子:
class Student implements Serializable {private static final long serialVersionUID = 3608451818006447637L;private String userName;private static String password = "123456";private transient int year = 24;//省略get set
}
我先调用serializeStudent()
进行序列化。
serializeStudent();
// deserializeStudent();
然后再调用deserializeStudent()
// serializeStudent();deserializeStudent();
可以看到输出:
HaC 123456 0
Student 对象反序列化成功!
在序列化写入文件的时候是 Student student1 = new Student("HaC", "HelloCoder", 30);
反序列化就有问题。在序列化时,因为它不会把序列化,所以反序列化只能拿到默认定义的值。
4、结论
1、网络传输、对象转换一定要使用序列化
2、实现这个Serializable 接口的时候,一定要给这个 serialVersionUID 赋值
3、static 、transient 修饰的属性不会反序列化。
详细聊聊 Java序列化和反序列化的作用相关推荐
- java 序列化概念和作用_结合代码详细解读Java序列化与反序列化概念理解
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- java序列化和反序列化以及序列化ID的作用分析
java序列化和反序列化 一.概念 java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象.对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一 ...
- 理论 | 教你彻底学会Java序列化和反序列化
这是小小本周的第四篇 Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件 ...
- Java中如何引用另一个类里的集合_【18期】Java序列化与反序列化三连问:是什么?为什么要?如何做?...
Java序列化与反序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: 序列化:对象序列化的最主要的用处就是在传递和保存对象 ...
- 教你彻底学会Java序列化和反序列化
Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件以后,在内存中重构对象 ...
- Java序列化与反序列化的深度思考
目录 1.序列化与反序列化的作用 2.序列化协议 2.1 JDK序列化协议 2.1.1 Externalizable与Serializable的异同 2.2 Google ProtocolBuf 协 ...
- Serializable详解(1):代码验证Java序列化与反序列化
说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...
- Java 序列化与反序列化
Java 序列化与反序列化 文章目录 Java 序列化与反序列化 1 序列化与反序列化的概念 2 核心类与关键字总览 3 序列化与反序列化的过程 3 应用示例 4 序列化版本号的作用 serialVe ...
- Java序列化和反序列化(详解)
一.理解Java序列化和反序列化 Serialization(序列化):将java对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存java对象状态的过程.序列化可以将数据永久保存在磁盘上(通常 ...
最新文章
- php 谷歌翻译api_科研福音,论文翻译神器系列!
- SAP C4C里销售订单行项目为什么无法添加产品
- java js 正则表达式_如何在JavaScript与Java中使用正则表达式
- python带通配符的字符串匹配_Bash技巧:实例介绍数个参数扩展表达式以处理字符串变量...
- ADPC2-G 希望
- WordPress后台添加侧边栏菜单
- 【性能测试】基本入门(包含mysql锁)
- pytorch根据特征图训练LSTM Stacked AutoEncoder
- 米筐量化不支持c语言_AQ答疑:三分钟入门量化投资
- 3.7 测试时的 Batch Norm
- CentOS7安装配置启动MySQL(附解决password does not satisfy)
- 我写了一本操作系统词典送你了
- 【android开发】手机应用管理器的实现之获取应用列表(一)
- 搭建Prometheus监控报警系统
- java使用egl_EGL 学习
- Unity EditorWindow Rename
- 乘法/积运算和符号(点乘/内积/数量积,叉乘/向量积,矩阵乘法,Hadamard, Kronecker积,卷积)一网打尽
- java中的字符串常量池_java字符串常量池
- JAVA大数据(2)--ZooKeeper Java API使用
- Java生鲜电商平台-技术方案与文档下载