最近本栈在阅读Java的源码,发现JDK的String类实现了Serializable接口,并定义了一个serialVersionUID变量,它知道这个接口是为了让String类能够序列化与反序列化,但是为什么要实现这个接口才能序列化与反序列化呢?

我们都知道,Serializable接口是为了让String对象可以被序列化与反序列化的,本着实践出真知的精神,我们一起来探索下如果不实现这个接口,会出现什么问题,加深下理解。

Serializable测试

以下是Serializable类的源码:

可以看到该类的内部实现完全为空,在Java IO体系中仅起一个标记的作用。那么这个标记具体是如何发挥作用的呢?我们测试一下:

首先定义一个User对象:

在idea中右键Generate...或者快捷键Alt + Insert 可以一键生成构造函数/set/get等。输入psvm一键生成public static void main,输入sout一键生成System.out.println()。更多可以用ctrl + j(mac上是command + j)查看。序列化的UID也可以一键生成,大家可以自行搜索。

接着我们定义一个类来读写这个User类的对象。

运行上述代码后,可以查看user.txt文件,其中的数据是以二进制的形式存在,有很多乱码,有一些关键词User,String。

�� sr thinking.in.java.common.User L idt Ljava/lang/String;L nameq ~ xpt 1001t Bob

此时User对象已经被持久化到文件中,接着我们将User实现Serializable接口的代码去掉,看会发生什么。

抛出了以上异常,提示不可序列化的异常,然后我们到ObjectOutputStream类中的1184行看一下,这一部分的代码是这样的:

如上所示,在else if中通过判断obj instanceof Serializable,如果对象没有实现序列化接口,就无法序列化。可以想见,Java中的每一处序列化都进行了类似的检查,也就是说,没有实现Serializable接口的对象是无法通过IO操作持久化

然后,我们测试反序列化,将文件中持久化的对象转换为Java对象。

打印信息为:

thinking.in.java.common.User@58372a00

此时如果将User实现Serializable接口的代码部分去掉,发现也无法将文本转换为序列化对象,反序列化异常:

通过这个异常信息,我们进入到ObjectInputStream类的源码中看看它是如何检查的。在874行,ObjectStreamClass进行了如下反序列的检查:

这里判断deserializeEx这个变量是否为null,如果不为null,就会抛出反序列化异常。关于这个变量变量是如何被赋值以及整个ObjectInputStream的反序列化过程由于过于复杂,就不在这里详细说明了。感兴趣的同学可以去看看这篇博客:https://yueyemaitian.iteye.com/blog/2078090。

SerialVersionUID

对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID,如:

private static final long serialVersionUID = 1L; 

在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的serialVersionUID与对应持久化时的类不同,那么反序列化的过程中将会导致InvalidClassException异常。例如,在之前反序列化的例子中,我们故意将User类的serialVersionUID改为2L,如:

private static final long serialVersionUID = 2L;

那么此时,在反序例化时就会导致异常,如下:

如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合,这样可能会导致在反序列化的过程中发生意外的InvalidClassException异常。因此,为了保证跨不同Java编译器实现的serialVersionUID值的一致,实现Serializable接口的必须显示地声明serialVersionUID字段。

此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!有个特殊的地方需要注意的是,数组类是不能显示地声明serialVersionUID的,因为它们始终具有默认计算的值,不过数组类反序列化过程中也是放弃了匹配serialVersionUID值的要求。

结论

通过上面的测试,相信大家对Serializable接口算是有了具体的体会了。事实上,序列化就是将对象转换为字节序列的过程,反序列化就是把持久化的字节文件数据恢复为对象的过程。

java 只去掉_30行代码带你了解Java的Serializable接口相关推荐

  1. 找不到libmmd.dll无法继续执行代码_300 行代码带你秒懂 Java 多线程!| 原力计划...

    作者 | 永远在路上[] 责编 | 胡巍巍 出品 | CSDN博客 线程线程的概念,百度是这样解释的:线程(英语:Thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际 ...

  2. 300 行代码带你秒懂 Java 多线程!| 原力计划

    作者 | 永远在路上[] 责编 | 胡巍巍 出品 | CSDN博客 线程 线程的概念,百度是这样解释的: 线程(英语:Thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的 ...

  3. 300 行代码带你秒懂 Java 多线程!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:终于放弃了单调的swagger-ui了,选择了这款神器-knife4j个人原创+1博客:点击前往,查看更多 线程 ...

  4. 宁愿“大小周”、每天只写 200 行代码、月薪 8k-17k 人群再涨!揭晓中国开发者真实现状...

    作者 | 郑丽媛 出品 | CSDN(ID:CSDNnews) 程序员,一个圈外人羡慕.圈内人喊苦的"神奇"职业--高薪.福利好是旁人羡慕的理由,高压.加班多却也是他们最常见的写照 ...

  5. 前几行 python_调包侠神器2.0发布,Python机器学习模型搭建只需要几行代码

    萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI Python开源机器学习建模库PyCaret,刚刚发布了2.0版本. 这款堪称「调包侠神器」的模型训练工具包,几行代码就能搞定模型编写.改进 ...

  6. 宁愿“大小周”、每天只写 200 行代码、月薪 8k-17k 人群再涨 | 揭晓中国开发者真实现状

    作者 | 郑丽媛 出品 | CSDN(ID:CSDNnews) 程序员,一个圈外人羡慕.圈内人喊苦的"神奇"职业--高薪.福利好是旁人羡慕的理由,高压.加班多却也是他们最常见的写照 ...

  7. hash签名 java_java开发区块链只需150行代码

    原标题:java开发区块链只需150行代码 本文帮助你理解什么是区块链.将通过java开发区块链的实战学习方式,用 Java创建开发一个基本的区块链,实现简单的工作量证明系统.Java开发区块链的源代 ...

  8. 5行代码带你爬取 “2021福布斯排行榜“,看看中国都有哪些人?

    今天是2021年8月20号,晚上坐在家里面,突然看到了2021福布斯排行榜的新闻.于是有感而发,写了这篇文章. 新闻 : 排行榜123网富豪频道为您提供2021年福布斯富豪榜,榜单包括2021世界首富 ...

  9. 【高代码文件格式API】道宁为您提供文件格式API集——Aspose,只需几行代码即可创建转换和操作100多种文件格式

    Aspose系列产品是 高代码文件格式API 使您的应用程序能够处理 适用于所有主要平台的 Word.Excel.PDF.PowerPoint.Outlook 和100多种其他文件格式 Aspose提 ...

最新文章

  1. 【Python】 更棒的Excel操作模块xlwings
  2. P3830-[SHOI2012]随机树【数学期望,dp】
  3. 怎样用bootsrapcol-md来实现四分屏_用会议平板提升会议效率,做好这两点
  4. 2018-11-02 在代码中进行中文命名实践的短期目标
  5. 你这样的“垃圾“,就应该进入老年代!!!
  6. JAVA实现置换加密和幻方加密(密码学)
  7. 程序员的那点事(转自java老师李明志)
  8. 动态生成节点与删除节点
  9. springboot集成梦网云科技api发送短信
  10. sim7020c功耗_SIM7020C NB-IoT HAT教程
  11. MySQL的三个锁级别(附图)
  12. 反距离加权法IDW C#实现
  13. 软件版权申请流程有哪些
  14. python3跑通smpl模型_SMPL模型改用python3+numpy计算
  15. 28届计算机表演赛辽宁赛区,第十九届计算机表演赛辽宁赛区网络基础类竞赛结果.doc...
  16. 用java计算某年某月的天数
  17. android 通知中心,你的 Android 通知中心从未如此井然有序过:个性通知
  18. “十步一杀” 消压力于无形
  19. 毕业设计-基于机器视觉道路视频车道线检测识别
  20. 安装双系统无法连接到软件服务器,MAC安装双系统,WIN10系统下不能登录qq,不能登录优酷,什么原因?...

热门文章

  1. 重庆市档案局(馆)数据备份一体机项目
  2. DirectX 9的坐标系统变换
  3. IHttpModule和IHttpHandler 应用笔记
  4. BufferedInputStream的read方法原理
  5. 公司--保存时验证数据是否保存重复
  6. 昌吉学院计算机工程系毕业后安排工作嘛,0昌吉学院.doc
  7. oracle找到引起账户锁定的ip,Oracle 找到引起账户锁定的IP
  8. php 降序 保留索引,PHP asort():对数组排序(升序),并保持索引关系
  9. html监听页面关闭事件,JS针对浏览器窗口关闭事件的监听方法集锦
  10. 如何打赢一场唯快不破的比赛,看看他们的绝招