序列化版本号serialVersionUID的作用_动力节点Java学院整理

序列化是Java中非常重要且常用的一个功能。它在实现网络通信、分布式存储等方面都有广泛的应用。而序列化版本号serialVersionUID则是保证序列化的兼容性和稳定性的重要手段,它用于判断序列化对象的版本是否一致,如果不一致则不能反序列化。

在Java中,每个class都有一个serialVersionUID属性,它是一个长整型数字。如果不显式指定,Java会自动生成一个serialVersionUID。当对象被序列化时,Java会将序列化对象的对象流中写入serialVersionUID,并且在反序列化时校验该数字。

serialVersionUID的作用就是当序列化一个对象时,Java会判断这个对象的serialVersionUID和本地JVM中对应的serialVersionUID是否一致。如果一致,则可以反序列化这个对象;如果不一致,则会抛出InvalidClassException异常,反序列化失败。

示例一:同一版本的序列化和反序列化

import java.io.*;

public class SerializationTest {

    private static final String FILE_PATH = "user.ser";

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User("张三", 20);
        System.out.println("序列化前: " + user);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH));
        oos.writeObject(user);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_PATH));
        User newUser = (User)ois.readObject();
        ois.close();
        System.out.println("序列化后: " + newUser);
    }

    private static class User implements Serializable {
        private String name;
        private int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}

执行结果如下:

序列化前: User{name='张三', age=20}
序列化后: User{name='张三', age=20}

示例二:不同版本的序列化和反序列化

import java.io.*;

public class SerializationTest {

    private static final String FILE_PATH = "user.ser";

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User("张三", 20);
        System.out.println("序列化前: " + user);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH));
        oos.writeObject(user);
        oos.close();
        // 修改User对象的属性age的类型为long
        File file = new File(FILE_PATH);
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        byte[] bytes = new byte[(int)randomAccessFile.length()];
        randomAccessFile.readFully(bytes);
        bytes[43] = 0x4C; // 修改0x10为0x4C
        randomAccessFile.seek(0);
        randomAccessFile.write(bytes);
        randomAccessFile.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_PATH));
        User newUser = (User)ois.readObject();
        ois.close();
        System.out.println("序列化后: " + newUser);
    }

    private static class User implements Serializable {
        private static final long serialVersionUID = 1L;
        private String name;
        private long age;

        public User(String name, long age) {
            this.name = name;
            this.age = age;
        }

        // 省略 toString 方法
    }
}

执行结果如下:

序列化前: User{name='张三', age=20}
Exception in thread "main" java.io.InvalidClassException: SerializationTest$User; local class incompatible: stream classdesc serialVersionUID = 7528517758001900623, local class serialVersionUID = 1

可以看到,当User对象被成功序列化后,我们故意修改了其属性age的类型,并重新读取了文件进行反序列化,我们得到了一个InvalidClassException异常的提示,反序列化失败。

在以上两个示例中,我们可以看到serialVersionUID属性的作用。当我们使用序列化功能时,一定要注意并理解这个字段的含义,以防止在使用中产生意外的错误。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:序列化版本号serialVersionUID的作用_动力节点Java学院整理 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java8之Lambda表达式使用解读

    Java8之Lambda表达式使用解读 什么是Lambda表达式? Lambda表达式是一种匿名函数,它没有名称,但它有参数列表、函数体和可能存在的返回类型,可以在需要函数类型的上下文中使用。 举个例子,我们可以使用Lambda表达式来实现简化的Runnable接口: Runnable r = () -> System.out.println(&quo…

    Java 2023年5月26日
    00
  • Commons beanutils组件简介

    Commons BeanUtils 组件简介 Commons BeanUtils 组件是 Apache Common 组件库中的一个组件,它提供了许多用于操作 JavaBean 对象的工具类。 功能介绍 Commons BeanUtils 主要提供以下几个方面的功能: 属性拷贝 BeanUtils 提供了一个 copyProperties() 方法,用于从一…

    Java 2023年6月15日
    00
  • Java连接postgresql数据库的示例代码

    接下来我来为您详细讲解Java连接PostgreSQL数据库的示例代码的完整攻略。 第一步:引入PostgreSQL的JDBC驱动 在使用Java连接PostgreSQL数据库之前,需要先下载并安装PostgreSQL的JDBC驱动。可以在 PostgreSQL官网 上下载对应的JDBC驱动。 完成下载和安装之后,需要在编码中引入JDBC驱动,代码如下: i…

    Java 2023年5月19日
    00
  • 解读Tomcat启动、重启、暂停操作(window)

    我来为您详细讲解“解读Tomcat启动、重启、暂停操作(window)”的完整攻略。 1. Tomcat启动操作 1.1. 检查JDK环境变量 首先要检查JDK 的环境变量设置是否正确。具体来说,需要检查以下环境变量: JAVA_HOME:JDK的安装目录路径。 CLASSPATH:Java运行时使用的类搜索路径。 PATH:系统的环境变量,需要将%JAVA…

    Java 2023年5月19日
    00
  • Spring security登录过程逻辑详解

    我将详细讲解“Spring security登录过程逻辑详解”的攻略。具体内容如下: 标题 Spring security登录过程逻辑详解 介绍 Spring Security是基于Spring的安全框架,提供了认证和授权的功能,是保障应用系统安全的重要组成部分。本文将详细介绍Spring Security的登录过程,并结合代码示例进行演示。 正文 Spri…

    Java 2023年5月20日
    00
  • 如何关闭 IDEA 自动更新

    下面是关于如何关闭 IDEA 自动更新的完整攻略: 1. 关闭 IDEA 自动更新 方式一:关闭自动检查更新 在 IDEA 的设置界面中,可以关闭自动检查更新功能,从而避免 IDEA 在启动时自动下载更新包。具体的操作步骤如下: 打开 IDEA,进入菜单栏,依次选择 “File” -> “Settings”(或者直接按下 “Ctrl+Alt+S” 快捷…

    Java 2023年5月26日
    00
  • SpringBoot读取资源目录中JSON文件的方法实例

    下面是关于”SpringBoot读取资源目录中JSON文件的方法实例”的完整攻略: 1.准备工作 首先需要在Spring Boot项目中创建一个资源目录,在其中添加一个JSON文件。 例如,在src/main/resources目录下创建json目录,然后在json目录下创建example.json文件,如下图所示: src/main/resources/j…

    Java 2023年5月26日
    00
  • Java 用两个线程交替打印数字和字母

    实现Java用两个线程交替打印数字和字母的方法,有很多种。下面给出两种简单明了的方法。 方式一: 使用synchronized关键字 首先,我们定义一个共享的线程类,需要一个计数用的整数类型变量、一个布尔类型的打印数字的标记、线程的名称及一个打印方法。 public class ShareThread { private int count = 1; pri…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部