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序列化和反序列化的作用相关推荐

  1. java 序列化概念和作用_结合代码详细解读Java序列化与反序列化概念理解

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  2. java序列化和反序列化以及序列化ID的作用分析

     java序列化和反序列化 一.概念 java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象.对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一 ...

  3. 理论 | 教你彻底学会Java序列化和反序列化

    这是小小本周的第四篇 Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件 ...

  4. Java中如何引用另一个类里的集合_【18期】Java序列化与反序列化三连问:是什么?为什么要?如何做?...

    Java序列化与反序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: 序列化:对象序列化的最主要的用处就是在传递和保存对象 ...

  5. 教你彻底学会Java序列化和反序列化

    Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件以后,在内存中重构对象 ...

  6. Java序列化与反序列化的深度思考

    目录 1.序列化与反序列化的作用 2.序列化协议 2.1 JDK序列化协议 2.1.1  Externalizable与Serializable的异同 2.2 Google ProtocolBuf 协 ...

  7. Serializable详解(1):代码验证Java序列化与反序列化

    说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...

  8. Java 序列化与反序列化

    Java 序列化与反序列化 文章目录 Java 序列化与反序列化 1 序列化与反序列化的概念 2 核心类与关键字总览 3 序列化与反序列化的过程 3 应用示例 4 序列化版本号的作用 serialVe ...

  9. Java序列化和反序列化(详解)

    一.理解Java序列化和反序列化 Serialization(序列化):将java对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存java对象状态的过程.序列化可以将数据永久保存在磁盘上(通常 ...

最新文章

  1. php 谷歌翻译api_科研福音,论文翻译神器系列!
  2. SAP C4C里销售订单行项目为什么无法添加产品
  3. java js 正则表达式_如何在JavaScript与Java中使用正则表达式
  4. python带通配符的字符串匹配_Bash技巧:实例介绍数个参数扩展表达式以处理字符串变量...
  5. ADPC2-G 希望
  6. WordPress后台添加侧边栏菜单
  7. 【性能测试】基本入门(包含mysql锁)
  8. pytorch根据特征图训练LSTM Stacked AutoEncoder
  9. 米筐量化不支持c语言_AQ答疑:三分钟入门量化投资
  10. 3.7 测试时的 Batch Norm
  11. CentOS7安装配置启动MySQL(附解决password does not satisfy)
  12. 我写了一本操作系统词典送你了
  13. 【android开发】手机应用管理器的实现之获取应用列表(一)
  14. 搭建Prometheus监控报警系统
  15. java使用egl_EGL 学习
  16. Unity EditorWindow Rename
  17. 乘法/积运算和符号(点乘/内积/数量积,叉乘/向量积,矩阵乘法,Hadamard, Kronecker积,卷积)一网打尽
  18. java中的字符串常量池_java字符串常量池
  19. JAVA大数据(2)--ZooKeeper Java API使用
  20. Java生鲜电商平台-技术方案与文档下载

热门文章

  1. 婚恋系统交友系统婚恋交友平台搭建红娘加盟积分充值兑换个人资料置顶同城交友系统
  2. HP 2029 HP46墨盒和佳能G1800 原装墨水耐久性短测
  3. 无需第三方软件,巧用系统自带功能开启共享WIFI
  4. 第1篇:幼儿园春节联欢晚会策划书
  5. linux的判断命令test之数值判断
  6. LeetCode658-找到k个最接近的元素
  7. CodeForces - 622E Ants in Leaves 贪心
  8. Flash 9 播放器\插件\卸载工具
  9. 【机器学习】ensemble learning
  10. JVM内存不要超过32G