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

news2024/9/20 1:10:46

目录

  • 前言
  • 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.coloradmin.cn/o/1367767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RuntimeError: CUDA error: invalid device ordinal解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Vue.js设计与实现阅读2

Vue.js设计与实现阅读-2 1、前言2、框架设计的核心要素2、1 提升用户体验2、2 控制代码体积2、3 Tree-Shaking2、4 特性开关2、5 错误处理 1、前言 上一篇我们了解到了 命令式和声明式的区别,前者关注过程,后者关注结果了解了虚拟dom存在的意义&#x…

[C#]winform部署yolov5-onnx模型

【官方框架地址】 https://github.com/ultralytics/yolov5 【算法介绍】 Yolov5,全称为You Only Look Once version 5,是计算机视觉领域目标检测算法的一个里程碑式模型。该模型由ultralytics团队开发,并因其简洁高效的特点而备受关注。Yol…

异常处理:全面覆盖与精细化管理的平衡

异常处理:全面覆盖与精细化管理的平衡 在软件开发中,异常处理是保证系统稳定性和用户体验的重要环节。对于是否应当全面覆盖所有异常并设立兜底机制,业界存在着两种主流思路:全面覆盖原则和精细化处理。如何在这两者间取得平衡&a…

嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序

介绍了如何搭建在Linux开发板中搭建Qt的运行环境,并测试了Qt自带的例程。 本篇,来介绍如何自己编写一个Qt程序,并将编译结果放到Linux开发板中运行。 1 Windows上编写Qt程序 因为Qt是支持跨平台的,所以我们可以先在Windows平台…

一天一个设计模式---单例模式

概念 单例模式是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。这意味着在应用程序中的任何地方,只能有一个实例存在,而不会创建多个相同类型的实例。 具体内容 单例模式通常包括以下几个要素…

深度学习:图神经网络——在推荐系统中的应用

PinSage是工业界应用图神经网络完成推荐任务的第一个成功案例,其从用户数据中构造图(graph)的方法和应对大规模图而采取的实现技巧都值得我们学习。PinSage被应用在图片推荐类Pinterest上。在Pinterest中,每个用户可以创建并命名图…

工程管理系统功能设计与实践:实现高效、透明的工程管理

在现代化的工程项目管理中,一套功能全面、操作便捷的系统至关重要。本文将介绍一个基于Spring Cloud和Spring Boot技术的Java版工程项目管理系统,结合Vue和ElementUI实现前后端分离。该系统涵盖了项目管理、合同管理、预警管理、竣工管理、质量管理等多个…

深入了解网络流量清洗--使用免费的雷池社区版进行防护

​ 随着网络攻击日益复杂,企业面临的网络安全挑战也在不断增加。在这个背景下,网络流量清洗成为了确保企业网络安全的关键技术。本文将探讨雷池社区版如何通过网络流量清洗技术,帮助企业有效应对网络威胁。 ![] 网络流量清洗的重要性&#x…

Wpf 使用 Prism 实战开发Day08

备忘录页面设计 1.效果图 一.布局设计跟第7章节一样&#xff0c;只是内容方面发生变化&#xff0c;其他样式都一样。直接把代码粘出来了 MemoView.xaml 页面代码 <UserControl x:Class"MyToDo.Views.MemoView"xmlns"http://schemas.microsoft.com/winfx/2…

jQuery页面整屏滚动

效果展示 jQuery页面整屏滚动 Html代码块 <div id"fullpage" class"fullpage-index"><!-- index01 --><div class"indexitem index01 section" id"#page1"><img src"img/img01.jpg"/></div>…

设计模式——工厂方法模式(Factory Method Pattern)

简单工厂模式 概述 说工厂方法模式之前&#xff0c;先说下简单工厂模式&#xff0c;简单工厂模式并不属于GoF 23个经典设计模式&#xff0c;但通常将它作为学习其他工厂模式的基础&#xff0c;它的设计思想很简单&#xff0c;其基本流程如下&#xff1a;首先将需要创建的各种不…

NODE笔记 0

一些简单的node学习笔记记录&#xff0c;是Vue等前端框架的基础 入门学习备忘录 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 node.js 内置网络服务器&#xff0c;是前端框架学习的基础&#xff1a; 概念&#xff1a;…

大模型机器人发展史:从VoxPoser、RT2到斯坦福Mobile ALOHA、Google机器人

前言 23年7月&#xff0c;我在朋友圈评估Google的RT2说道&#xff1a; “大模型正在革新一切领域啊&#xff0c;超帅&#xff0c;通过大模型不仅能理解“人话”&#xff0c;还能对“人话”进行推理&#xff0c;并转变为机器人能理解的指令&#xff0c;从而分阶段完成任务。回…

Web前端-jQuery

文章目录 jQuery1.1 jQuery 介绍1.1.1 JavaScript 库1.1.2 jQuery的概念1.1.3 jQuery的优点 1.2 jQuery 的基本使用1.2.1 jQuery 的下载1.2.2 jQuery快速入门1.2.3 jQuery入口函数1.2.4 jQuery中的顶级对象$1.2.5 jQuery 对象和 DOM 对象1.2.6. jQuery 对象和 DOM 对象转换 1.3…

二叉树OJ练习(二)

1. 二叉树的最近公共祖先 题目描述&#xff1a; ​ 题解: 1.p或者q其中一个等于root&#xff0c;那么root就是最进公共祖先 2.p和q分布在root的左右两侧&#xff0c;那么root就是最进公共祖先 3.p和q在root的同一侧&#xff0c;就是要遍历这棵树&#xff0c;遇到p或者q返回 ​…

数据结构—图(下)

文章目录 12.图(下)(4).生成树和最小生成树#1.什么是生成树和最小生成树&#xff1f;i.生成树ii.最小生成树 #2.Prim算法i.算法思想ii.看看例子iii.代码实现 #3.Kruskal算法i.算法思想ii.看看例子iii.代码实现 #4.次小生成树 (5).最短路径问题#1.加权有向图的最短路径问题#2.单…

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

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

鹦鹉目标检测数据集VOC格式600张

鹦鹉&#xff0c;一种色彩鲜艳、聪明伶俐的鸟类&#xff0c;以其模仿人类语言的能力和独特的喙形而广受喜爱。 鹦鹉属于鸟纲、鹦鹉科&#xff0c;是热带和亚热带地区的常见鸟类。它们的喙弯曲呈钩状&#xff0c;非常适合啄食种子、果实和坚果等食物。鹦鹉的羽毛通常非常鲜艳&a…

精进单元测试技能——Pytest断言的艺术

本篇文章主要是阐述Pytest在断言方面的应用。让大家能够了解和掌握Pytest针对断言设计了多种功能以适应在不同测试场景上使用。 了解断言的基础 在Pytest中&#xff0c;断言是通过 assert 语句来实现的。简单的断言通常用于验证预期值和实际值是否相等&#xff0c;例如&#xf…