serialVersionUID 的规范

Serializable 和 Externalizable

Java类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。

如果读者看过Serializable的源码,就会发现,他只是一个空的接口,里面什么东西都没有。Serializable接口没有方法或字段,仅用于标识可序列化的语义。但是,如果一个类没有实现这个接口,想要被序列化的话,就会抛出java.io.NotSerializableException异常。

序列号在写成二进制流的时候,会调用如下的方法:

Externalizable继承自Serializable,该接口中定义了两个抽象方法:writeExternal()与readExternal()。

当使用Externalizable接口来进行序列化与反序列化的时候需要开发人员重写writeExternal()与readExternal()方法。否则所有变量的值都会变成默认值。

transient 不需要被序列化

transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

什么是 serialVersionUID

序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道,Java对象是保存在JVM的堆内存中的,也就是说,如果JVM堆不存在了,那么对象也就跟着消失了。

而序列化提供了一种方案,可以让你在即使JVM停机的情况下也能把对象保存下来的方案。就像我们平时用的U盘一样。把Java对象序列化成可存储或传输的形式(如二进制流),比如保存在文件中。这样,当再次需要这个对象的时候,从文件中读取出二进制流,再从二进制流中反序列化出对象。

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致,这个所谓的序列化ID,就是我们在代码中定义的serialVersionUID。

这是因为,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

为什么必须设置默认的 serialVersionUID 值

如果我们没有在类中明确的定义一个serialVersionUID的话,看看会发生什么。

尝试修改上面的demo代码,先使用以下类定义一个对象,该类中不定义serialVersionUID,将其写入文件。

然后我们修改User1类,向其中增加一个属性。在尝试将其从文件中读取出来,并进行反序列化。

执行结果:

java.io.InvalidClassException: com.hollis.User1; local class incompatible: stream classdesc serialVersionUID = -2986778152837257883, local class serialVersionUID = 7961728318907695402

同样,抛出了InvalidClassException,并且指出两个serialVersionUID不同,分别是-2986778152837257883和7961728318907695402。

从这里可以看出,系统自己添加了一个serialVersionUID。

所以,一旦类实现了Serializable,就建议明确的定义一个serialVersionUID。不然在修改类的时候,就会发生异常。

serialVersionUID有两种显示的生成方式:

一种是默认的1L,比如:

private static final long serialVersionUID = 1L;

另外一种是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:

private static final long serialVersionUID = xxxxL;

后面这种方式,可以借助IDE生成,后面会介绍。

背后原理

为了简化代码量,反序列化的调用链如下:

在initNonProxy中 ,关键代码如下:

在反序列化过程中,对serialVersionUID做了比较,如果发现不相等,则直接抛出异常。

深入看一下getSerialVersionUID方法:

在没有定义serialVersionUID的时候,会调用computeDefaultSUID 方法,生成一个默认的serialVersionUID。

这也就找到了以上两个问题的根源,其实是代码中做了严格的校验,并且在未定义的时候自动生成了一个serialVersionUID。

IDEA提示

为了确保我们不会忘记定义serialVersionUID,可以调节一下Intellij IDEA的配置,在实现Serializable接口后,如果没定义serialVersionUID的话,IDEA(eclipse一样)会进行提示:

并且可以一键生成一个:

当然,这个配置并不是默认生效的,需要手动到IDEA中设置一下:

在图中标号3的地方(Serializable class without serialVersionUID的配置),打上勾,保存即可。

序列号 java_JAVA序列号的serialVersionUID相关推荐

  1. iphonex 序列号_iPhonex如何查看序列号 iPhonex序列号查看有哪些方法

    iPhonex很多小伙伴已经入手了,初使用iPhonex的小伙伴对于iPhonex还不是很熟悉,一些小伙伴想知道iPhonex如何查看序列号,下面就让小编为大家介绍一下iPhonex序列号查看方法,感 ...

  2. c# 获取本机 MAC地址\序列号\硬盘序列号

    View Code  1   /// <summary>  2         /// 显示MAC地址  3         /// </summary>  4         ...

  3. 用C#获取硬盘序列号,CPU序列号,网卡MAC地址

    这个问题首先得考虑的就是你的硬盘是不是SCSI硬盘 如果是,那么根本不存在"物理序列号",只可能取得卷标的序列号 如果是卷标序列号,要注意的是每次格式化硬盘的时候这个序列号都会变 ...

  4. Python获取硬件信息(硬盘序列号,CPU序列号)

    原文衔接 https://www.cnblogs.com/blog-rui/p/12108072.html pip install wmi pip install pywin32 import wmi ...

  5. iphonex 序列号_iPhoneX序列号在哪 苹果X序列号怎么看?

    对于后续准备入手iPhoneX的果粉来说,很多朋友拿到真机之后都想知道自己买到是不是正品.水货之类的.其实一般情况下除了通过外观真机.配件之外去辨别之外,我们还可以通过iPhoneX序列号去查看.对于 ...

  6. iphonex 序列号_iPhoneX序列号在哪?苹果iPhoneX序列号怎么看?

    iPhoneX怎么辨别真假?iPhoneX序列号在哪?苹果iPhoneX序列号怎么看?很多朋友拿到苹果X真机之后不确定知道自己买到的是不是正品.水货之类的.从外观.配件又不好辨别,此事我们可以通过iP ...

  7. 思科序列号无服务器,查看思科设备序列号以及序列号的命名格式

    对于思科网络设备来说,设备的序列号(Serial Number)至关重要,序列号是出厂的时候就决定的唯一标识,在网络工程师的日常工作中,可能经常需要和序列号打交道.那么具体我们应该如何查看这些序列号, ...

  8. iphonex 序列号_iPhonex序列号在哪看?iPhonex序列号查看方法介绍[图]

    最近关于iphonex的各种消息不断,可以看出来这款手机真的很受欢迎,很多网友在问,对于iphonex的正版序列号怎么查询还不太清楚,那么这个序列号在哪儿看呢?安族小编整理了资料和大家分享下吧! iP ...

  9. 序列号及序列号生成器(号段模式,数据库模式)详细介绍(建议收藏)

    前言 现如今,数据的唯一性和可追溯性变得越来越重要.从简单的数据库主键到复杂的分布式系统,唯一标识符在各种场景中都发挥着关键作用.序列号,作为一种广泛应用的唯一标识符,为我们提供了确保数据完整性和一致 ...

  10. mysql 模拟 序列号_mysql 序列号生成器(转)

    如果你不想使用mysql的自动递增,但又想实现主键序列号的功能,可以使用下面的方法,通过函数用一张表去维护生成多个表的序列号,简单又实用 1.创建生成多个表的序列号的数据维护表 CREATE TABL ...

最新文章

  1. ARCGIS影像配准教程
  2. 【撸啊撸 Docker】搭建 Jenkins
  3. JavaScript 严格模式(use strict)
  4. jquery ajax 跨域请求
  5. 成都理工大学“自然地理学”专业转行AI之路(精彩直播回放)
  6. 90%做tiktok运营都存在的误区?
  7. 谷歌Chrome浏览器无法打开网页,提示您与此网站之间建立不安全连接【解决】
  8. C陷阱与缺陷-1理解函数申明
  9. K60笔记2——内存空间分布
  10. 一个简单易用的m3u8下载器,支持下载m3u8链接或文件为mp4或ts格式
  11. 电脑屏幕网页字体大小怎么调整?
  12. 电视机关机特效——android
  13. mysql sock_mysql.sock 文件解析
  14. 深入理解栈(Stack)
  15. XFP模块和SFP光模块
  16. Hotspot Object本地方法实现 源码解析
  17. python 生成器、列表/字典/集合解析式区别
  18. 水晶报表 小代码大作用【BY 阿泰】
  19. C语言—递归函数有5个人围坐在一起,问第5个人多大年纪,他说比第4个人大2岁;问第4个人,他说比第3个人大2岁;问第3个人,他说比第2个人大2岁;问第2个人,他说比第1个人大2岁。第1个人说自己10岁
  20. 扒开思派健康招股书:大数据的面子,“卖药”的里子

热门文章

  1. word打开文档很久很慢_打开Office文档很慢的解决办法
  2. ltm是什么门的缩写_公司简报中的“LTM EBITDA”是什么意思啊?对应的中文是什么?...
  3. R语言-豆瓣电影top250数据爬取和分析
  4. 对JavaWeb项目中WEB-INF目录的理解
  5. 【Java】抽象类和接口的区别
  6. 伦敦银持仓分布分析技巧
  7. dismiss ios pop效果_动画切换效果之push、pop、present、dismiss
  8. 向flume发送消息出现Client sent event exceeding the maximum length
  9. 【玩转linux】head命令
  10. 【Unity3D日常开发】Unity3D中实现箭头指向目标点的效果