返回顶部
首页 > 资讯 > 精选 >SerialVersionUID有什么作用
  • 191
分享到

SerialVersionUID有什么作用

2023-06-16 17:06:30 191人浏览 泡泡鱼
摘要

本文小编为大家详细介绍“SerialVersionUID有什么作用”,内容详细,步骤清晰,细节处理妥当,希望这篇“SerialVersionUID有什么作用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Seria

本文小编为大家详细介绍“SerialVersionUID有什么作用”,内容详细,步骤清晰,细节处理妥当,希望这篇“SerialVersionUID有什么作用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

Serializable 和 Externalizable

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

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

它是怎么保证只有实现了该接口的方法才能进行序列化与反序列化的呢?

原因是在执行序列化的过程中,会执行到以下代码:

SerialVersionUID有什么作用

在进行序列化操作时,会判断要被序列化的类是否是Enum、Array和Serializable类型,如果都不是则直接抛出NotSerializableException。

Java中还提供了Externalizable接口,也可以实现它来提供序列化能力。

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

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

transient

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

自定义序列化策略

在序列化过程中,如果被序列化的类中定义了writeObject 和 readObject 方法,虚拟机会试图调用对象类里的 writeObject 和  readObject 方法,进行用户自定义的序列化和反序列化。

如果没有这样的方法,则默认调用是 ObjectOutputStream 的 defaultWriteObject方法以及  ObjectInputStream 的 defaultReadObject 方法。

用户自定义的 writeObject 和 readObject 方法可以允许用户控制序列化的过程,比如可以在序列化的过程中动态改变序列化的数值。

所以,对于一些特殊字段需要定义序列化的策略的时候,可以考虑使用transient修饰,并自己重写writeObject 和 readObject  方法,如java.util.ArrayList中就有这样的实现。

以上,就是一些读者需要掌握和和序列化有关的知识。

我们随便找几个Java中实现了序列化接口的类,如String、Integer等,我们可以发现一个细节,那就是这些类除了实现了Serializable外,还定义了一个serialVersionUID

SerialVersionUID有什么作用

那么,到底什么是serialVersionUID呢?为什么要设置这样一个字段呢?

什么是serialVersionUID

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

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

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

如果serialVersionUID变了会怎样

我们举个例子吧,看看如果serialVersionUID被修改了会发生什么?

SerialVersionUID有什么作用

我们先执行以上代码,把一个User1对象写入到文件中。然后我们修改一下User1类,把serialVersionUID的值改为2L。

SerialVersionUID有什么作用

然后执行以下代码,把文件中的对象反序列化出来:

SerialVersionUID有什么作用

执行结果如下:

java.io.InvalidClassException: com.hollis.User1; local class incompatible:  stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

可以发现,以上代码抛出了一个java.io.InvalidClassException,并且指出serialVersionUID不一致。

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

这也是《阿里巴巴Java开发手册》中规定,在兼容性升级中,在修改类的时候,不要修改serialVersionUID的原因。除非是完全不兼容的两个版本。所以,serialVersionUID其实是验证版本一致性的。

如果读者感兴趣,可以把各个版本的jdk代码都拿出来看一下,那些向下兼容的类的serialVersionUID是没有变化过的。比如String类的serialVersionUID一直都是-6849794470754667710L。

但是,作者认为,这个规范其实还可以再严格一些,那就是规定:

如果一个类实现了Serializable接口,就必须手动添加一个private static final long  serialVersionUID变量,并且设置初始值。

为什么要明确定一个serialVersionUID

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

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

SerialVersionUID有什么作用

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

SerialVersionUID有什么作用

执行结果:

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生成,后面会介绍。

背后原理

知其然,要知其所以然,我们再来看看源码,分析一下为什么serialVersionUID改变的时候会抛异常?在没有明确定义的情况下,默认的serialVersionUID是怎么来的?

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

SerialVersionUID有什么作用

在initNonProxy中 ,关键代码如下:

SerialVersionUID有什么作用

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

深入看一下getSerialVersionUID方法:

SerialVersionUID有什么作用

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

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

IDEA提示

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

SerialVersionUID有什么作用

并且可以一键生成一个:

SerialVersionUID有什么作用

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

SerialVersionUID有什么作用

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

读到这里,这篇“SerialVersionUID有什么作用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: SerialVersionUID有什么作用

本文链接: https://www.lsjlt.com/news/284403.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • SerialVersionUID有什么作用
    本文小编为大家详细介绍“SerialVersionUID有什么作用”,内容详细,步骤清晰,细节处理妥当,希望这篇“SerialVersionUID有什么作用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Seria...
    99+
    2023-06-16
  • serialversionuid是什么及有什么作用
    本篇内容主要讲解“serialversionuid是什么及有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“serialversionuid是什么及有什么作用”吧!serialversio...
    99+
    2023-07-02
  • serialVersionUID有什么用
    这期内容当中小编将会给大家带来有关serialVersionUID有什么用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。序列化是一种对象持久化的手段。普遍应用在网络传输、RMI等场景中。类通过实现 jav...
    99+
    2023-06-19
  • 什么是serialVersionUID
    serialVersionUID是Java中的一个静态常量,用于标识序列化类的版本号。当一个类实现了Serializable接口,即...
    99+
    2023-09-09
    serialVersionUID
  • Java SerialVersionUID作用详解
    问题1:Serializable是什么 首先,说说Serializable是实现java将内存中的类存储至硬盘中而使用的 一个类使用了Serializalbe接口,在序列化到文件时,...
    99+
    2024-04-02
  • serialVersionUID作用全面解析
    serialVersionUID适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相...
    99+
    2023-05-31
    serialversionuid 作用
  • postgresql有什么作用
    小编给大家分享一下postgresql有什么作用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!PostgreSQL 是一个免费的...
    99+
    2024-04-02
  • mysql有什么作用
    小编给大家分享一下mysql有什么作用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!众所周知,MySQL是一种关系数据库管理系统...
    99+
    2024-04-02
  • phpmyadmin有什么作用
    这篇文章将为大家详细讲解有关phpmyadmin有什么作用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。phpMyAdmin是一个以PHP为基础,以Web-Base方式架...
    99+
    2024-04-02
  • css3有什么作用
    这篇文章主要介绍“css3有什么作用”,在日常操作中,相信很多人在css3有什么作用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”css3有什么作用”的疑惑有所帮助!接下来,...
    99+
    2024-04-02
  • js有什么作用
    这篇文章将为大家详细讲解有关js有什么作用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程...
    99+
    2024-04-02
  • Ajax有什么作用
    这篇文章将为大家详细讲解有关Ajax有什么作用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。ajax简介AJAX即“Asynchronous Javascript And...
    99+
    2024-04-02
  • HTML有什么作用
    这篇文章主要介绍了HTML有什么作用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。HTML介绍   HTML 是用来描述网页的一种...
    99+
    2024-04-02
  • ajaxError()有什么作用
    这篇文章主要为大家展示了“ajaxError()有什么作用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ajaxError()有什么作用”这篇文章吧。   无...
    99+
    2024-04-02
  • JSON有什么作用
    这篇文章主要介绍“JSON有什么作用”,在日常操作中,相信很多人在JSON有什么作用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JSON有什么作用”的疑惑有所帮助!接下来,...
    99+
    2024-04-02
  • nodejs有什么作用
    这篇文章主要为大家展示了“nodejs有什么作用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“nodejs有什么作用”这篇文章吧。一、概览1、html可以在浏览...
    99+
    2024-04-02
  • JavaScript有什么作用
    JavaScript的作用有:1、为网页添加各式各样的动态功能,例如在HTML页面中嵌入动态文本;2、对浏览器事件做出响应;3、能够读写HTML元素的内容;4、在数据被提交到服务器之前,用JavaScript来验证数据;5、可用JavaSc...
    99+
    2024-04-02
  • cdn有什么作用
    cdn的作用:使打开网站速度变快、减少跳出率,增加用户好感。能够保障在流量过高、间歇性高峰和潜在服务器故障等高压力情况下,依旧可以正常访问网站。cdn加速覆盖全球的线路,通过和运营商合作,部署IDC资源,在全国骨干节点上,合理部署cdn边缘...
    99+
    2024-04-02
  • vps有什么作用
    本篇内容介绍了“vps有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!vps是什么vps又称为虚拟专用服务器,是指利用虚拟服务器软件...
    99+
    2023-06-07
  • VBScript有什么作用
    小编给大家分享一下VBScript有什么作用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!VBScript的作用 计算 2. 处理文件和文件夹 3. 管理Wind...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作