详解Java中的serialVersionUID概念以及作用(附上Demo)

目录

  • 前言
  • 1. 概念
  • 2. Demo

前言

原本实现Serializable接口的时候一直都没有serialVersionUID属性,直到看到涉及MybatisPlus新项目中都有该属性,于是做了一期学习了解,最后发现该属性类似深度学习训练中的种子seed,类似版本控制!

1. 概念

serialVersionUID 是 Java 中用于版本控制序列化的一个字段。

手动方式默认值为1L,比如:private static final long serialVersionUID = 1L

  • 一个长整型数值
  • 是一个 private static final long 类型的字段,用于标识一个类的序列化版本号
  • 在序列化和反序列化过程中,serialVersionUID 被用来验证序列化对象和反序列化对象的类是否兼容,即是否是同一个类的不同版本。
作用(为什么需要)生成方式(功能意义)注意事项
1.用于标识类的版本,确保序列化和反序列化的兼容性。如果两个类的 serialVersionUID 不同,Java 将不会进行序列化和反序列化,以避免版本不一致导致的问题。

2.冲突解决: 在类的结构发生变化时,通过手动指定 serialVersionUID 可以防止默认生成的版本号发生变化,从而避免潜在的冲突。
1.自动生成: 如果一个类没有显式声明 serialVersionUID,Java 序列化机制会根据类的结构自动生成一个版本号。

2.手动生成: 开发人员可以通过手动在类中定义 private static final long serialVersionUID 来指定版本号,以便在类结构发生变化时能够更加精确地控制版本。
1.如果不显式指定 serialVersionUID,Java 将根据类的结构自动生成。这种自动生成的方式可能不够稳定,因此在需要进行序列化的类中最好显式指定 serialVersionUID。

2.当类的结构发生变化时,手动指定 serialVersionUID 可以防止默认生成的版本号发生变化,避免潜在的序列化问题。

类似的代码如下:

import java.io.Serializable;public class MyClass implements Serializable {private static final long serialVersionUID = 1L;// other class members and methods
}

在这个示例中,MyClass 类显式地指定了 serialVersionUID 为 1L,以确保在类的结构发生变化时能够更好地进行版本控制

对于Serializable 类,其源码只是一个接口:public interface Serializable { }

总的来说:

serialVersionUID 是根据类的结构计算得到的哈希值,通常为负数。这个值是通过对类的结构进行哈希运算而生成的,因此不同版本的类将具有不同的 serialVersionUID。其存在的主要目的是为了处理序列化和反序列化过程中的版本兼容性问题。

当一个类被序列化后,其字节表示可能会存储在磁盘上或通过网络传输到不同的 JVM(Java 虚拟机)。如果类的结构发生了变化,例如添加了新的字段或方法,反序列化时就可能出现版本不一致的问题。为了解决这个问题,引入了 serialVersionUID 的概念。

以下是对 serialVersionUID 的功能和作用的总结:

  • 版本兼容性
    serialVersionUID 的存在是为了确保序列化和反序列化的版本兼容性。
    当类的结构发生变化时,不同版本的类将具有不同的 serialVersionUID。
    在序列化和反序列化过程中,Java 使用 serialVersionUID 来验证类的版本是否一致,以防止版本不匹配引发的问题。

  • 自动生成和手动生成:(上述已阐述)

  • 兼容性处理:
    当反序列化旧版本的对象时,如果新版本的类中删除了某些字段或方法,Java 虚拟机会忽略这些字段或方法,而不会引发异常。
    这种处理方式允许在一定程度上保持不同版本的类的兼容性,使得应用程序在进行升级时更加灵活。

总体而言,serialVersionUID 是一个重要的概念,用于确保序列化和反序列化过程中类的版本兼容性,同时提供了灵活的手动生成方式,使开发人员能够更好地控制类的版本信息。

2. Demo

为了更加方便的显示serialVersionUID的作用,可看下方的例子

原本Entity中有一个实体类,实现了Serializable 类

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("test_user")
public class User implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private int id;private String username;private String password;// 其他字段...}

通过序列化User的对象,并再次反序列化读取对象:

import java.io.*;public class SerializationDemo {// 序列化对象public static void serializeUser(User user, String filename) throws IOException {try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) {out.writeObject(user);}}// 反序列化读取对象public static User deserializeUser(String filename) throws IOException, ClassNotFoundException {try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {return (User) in.readObject();}}public static void main(String[] args) throws IOException, ClassNotFoundException {// 创建一个 User 对象并序列化保存User user = new User(123,"manong", "123");serializeUser(user, "user.ser");// 反序列化读取 Person 对象User deserializedPerson = deserializeUser("user.ser");System.out.println("Deserialized User: " + deserializedPerson);}
}

执行得到的结果为:Deserialized User: User(id=123, username=manong, password=123)

截图如下:

在这里插入图片描述


如果在此时修改版本(假设开发者不知道其版本),并且增加属性:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("test_user")
public class User implements Serializable {// 修改位置private static final long serialVersionUID = 2L;@TableId(value = "id", type = IdType.AUTO)private int id;private String username;private String password;// 其他字段...private String ceshi;}

对应反序列化改为如下:

    public static void main(String[] args) throws IOException, ClassNotFoundException {// 创建一个 User 对象并序列化保存
//        User user = new User(123,"manong", "123");
//        serializeUser(user, "user.ser");try {// 反序列化读取 Person 对象User deserializedPerson = deserializeUser("user.ser");System.out.println("Deserialized User: " + deserializedPerson);}catch (IOException | ClassNotFoundException e) {System.err.println("Error deserializing: " + e.getMessage());}}

根绝提示bug,也可看出不匹配:

Error deserializing: com.example.demo.entity.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

截图如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/233804.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java课程设计个人博客

目录 引言:在此说明在本次课设过程中所遇到的困难! 一、项目搭建的问题 Q1:Web项目应用啥么编译器编写? Q2:如何创建Web项目(MAVEN)? Q3:Tomcat服务器开头控制台显示乱码如何解决? Q4:Tomcat服务器怎么设置项目的…

Maven之私服

1 介绍 团队开发现状分析私服是一台独立的服务器,用于解决团队内部的资源共享与资源同步问题Nexus Sonatype公司的一款maven私服产品 下载地址:https://help.sonatype.com/repomanager3/download win版安装包:https://pan.baidu.com/s/1wk…

Mysql :Failed to obtain JDBC Connection

驱动版本需要跟新&#xff0c;同时驱动对应的pom依赖需要更新成mysql驱动对应版本&#xff0c;这里使用8.0.26版本。 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector}<…

MySQL之子查询、连接查询(内外)以及分页查询(实操)

文章目录 前言一、SQL脚本二、实操以及实现思路 前言 续上篇博主MySQL之视图&索引&执行计划这篇给大家讲解MySQL之子查询、连接查询(内&外)以及分页查询 一、SQL脚本 /*Navicat Premium Data TransferSource Server : localhostSource Server Type :…

芯课堂 | 如何配置SWM系列系统时钟?

如何配置SWM系列 系统时钟&#xff1f; 华芯微特科技有限公司SWM系列芯片可通过软件配置改变时钟的速度&#xff0c;可以让我们的设计更加灵活,频率可选空间也更加广泛&#xff0c;用户可以根据自己的实际需求配置需要的系统时钟。为了让用户能够更简单的使用这一功能&#xf…

(Matlab)基于CNN-Bi_LSTM的多维时序回归预测(卷积神经网络-双向长短期记忆网络)

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码展示&#xff1a; 四、完整代码数据下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平…

【ASP.NET Core 基础知识】--项目结构

一、ASP.NET Core项目的基本结构 ASP.NET Core项目的基本结构通常遵循一种标准的组织方式&#xff0c;这有助于提高项目的可维护性和可扩展性。以下是一个典型的ASP.NET Core项目的基本结构&#xff1a; 项目文件 (.csproj): 项目的主要配置文件&#xff0c;定义了项目的依…

第二百五十三回

文章目录 概念介绍使用方法示例代码 概念介绍 进度条是常用的组件之一&#xff0c;它主要用来显示某种动作的完成进度。Flutter提供了多种进度条组件&#xff0c;常用的是水平进度条&#xff1a;LinearProgressIndicator&#xff1b;圆形进度条 :CircularProgressIndicator和R…

C++——冒泡排序

作用&#xff1a;最常用的排序算法&#xff0c;对数组内元素进行排序 1&#xff0c;比较相邻的元素&#xff0c;如果第一个比第二个大&#xff0c;就交换他们两个。 2&#xff0c;对每一对相邻元素做同样的工作&#xff0c;执行完毕后&#xff0c;找到第一个最大值。 3&…

朴素贝叶斯(Naive Bayes)

朴素贝叶斯&#xff08;Naive Bayes&#xff09;是一组基于贝叶斯定理的分类算法&#xff0c;它基于特征之间的独立性假设&#xff0c;因此被称为“朴素”。尽管这个假设在实际情况中往往不成立&#xff0c;但朴素贝叶斯在实践中表现得相当好&#xff0c;并在文本分类和垃圾邮件…

带前后端H5即时通讯聊天系统源码

带有前后端的H5即时通讯聊天系统源码。该源码是一个开源的即时通信demo&#xff0c;需要前后端配合使用。它的主要目的是为了促进学习和交流&#xff0c;并为大家提供开发即时通讯功能的思路。尽管该源码提供了许多功能&#xff0c;但仍需要进行自行开发。该项目最初的开发初衷…

爬虫实战 - 微博评论数据可视化

简介&#xff1a; 我们都知道在数据比较少的情况下&#xff0c;我们是可以很轻易的获取到数据中的信息。但是当数据比较庞大的时候呢&#xff0c;我们就很难看出来了。尤其是面对现如今数以万计的数据&#xff0c;就更了。 不过好在我们可以通过计算机来帮我们进行分析&#…

如何查看崩溃日志

目录 描述 思路 查看ipa包崩溃日志 简单查看手机崩溃信息几种方式 方式1:手机设置查看崩溃日志 方式2: Xocde工具 方式3: 第三方软件克魔助手 环境配置 实时日志 奔溃日志分析 方式四&#xff1a;控制台资源库 线上崩溃日志 线上监听crash的几种方式 方式1: 三方平…

vue3 封装一个按钮组件(可自定义按钮样式)

效果图 鼠标悬浮有对应的文字提示&#xff0c;且图标出现背景色和颜色 实现 目前提供五个固定样式的图标及三个用户自定义的图标&#xff0c;可根据需要补充 组件代码 <script setup lang"ts"> import { onMounted, PropType, reactive, ref, watch } from v…

HarmonyOS应用开发之ArkTS语言学习记录

1、ArkTS介绍 ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风格的基础上&#xff0c;对TS的动态类型特性施加更严格的约束&#xff0c;引入静态类型。同时&#xff0c;提供了声明式UI、状态管理等相应的能力&#xff0c;让开发者…

Qt/C++音视频开发63-设置视频旋转角度/支持0-90-180-270度旋转/自定义旋转角度

一、前言 设置旋转角度&#xff0c;相对来说是一个比较小众的需求&#xff0c;如果视频本身带了旋转角度&#xff0c;则解码播放的时候本身就会旋转到对应的角度显示&#xff0c;比如手机上拍摄的视频一般是旋转了90度的&#xff0c;如果该视频文件放到电脑上打开&#xff0c;…

lv14 IO模型:阻塞和非阻塞 7

1 五种IO模型------读写外设数据的方式 阻塞: 不能操作就睡觉 非阻塞&#xff1a;不能操作就返回错误(通过轮询即才能实现阻塞的情况 &#xff09; 多路复用&#xff1a;委托中介监控 信号驱动&#xff1a;让内核如果能操作时发信号&#xff0c;在信号处理函数中操作 异步IO&a…

npm报错error:03000086:digital envelope routines::initialization error

可能是因为node版本过高&#xff0c;与现在的项目不符合 这是降低node版本的命令&#xff0c;然后重新运行 npm install npm8.1.2 -g

LUT预设.cube格式PR/达芬奇/FCP/剪映等视频电影调色预设LUTs

对于将标准镜头转换为让人想起高端电影的视觉冲击场景至关重要。这些LUT经过专业设计&#xff0c;以模仿电影行业中的电影质量、深度和情感&#xff0c;使其成为电影制作人、摄像师和内容创作者的理想选择&#xff0c;希望为你的作品带来专业的电影色彩。 电影LUT的类别&#…

三种解密 HTTPS 流量的方法介绍

Web 安全是一项系统工程&#xff0c;任何细微疏忽都可能导致整个安全堡垒土崩瓦解。拿 HTTPS 来说&#xff0c;它的「内容加密、数据完整性、身份认证」三大安全保证&#xff0c;也会受到非法根证书、服务端配置错误、SSL 库漏洞、私钥被盗等等风险的影响。很多同学认为只要访问…