serialVersionUID简要介绍

serialVersionUID是在Java序列化、反序列化对象时起作用的一个字段。Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidClassException。

序列化是一种把对象持久化到外部的手段。在网络传输等场景中应用广泛,如Dubbo等框架。类通过实现 java.io.Serializable 接口以启用其序列化功能。

阿里Java规约中的描述

阿里规约中强制性的提醒,修改serialVersionUID字段,会引起反序列化失败的情况。

代码演示

下面,通过实际代码,来演示对象序列化、反序列化的操作。

引入依赖

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>

commons-lang3这个包有帮我们实现了序列化的工具类,commons-io帮我们实现了文件操作的工具类,junit用来写单元测试。

序列化

有User.class如下:

@Data
@Builder
public class User implements Serializable { private static final long serialVersionUID = 1L; private String username; }

@Data 和 @Builder 是Lombok里面的注解,可以自动生成getter、setter方法等,不懂的可以查看我之前的文章,对这个有讲解。

需要序列化的类,需要实现Serializable接口,Serializable是一个标识接口,里面没有具体需要实现的东西。

序列化代码:

@Test
public void serializeTest() throws IOException {
User user = User.builder().username("happyjava").build();
byte[] serialize = SerializationUtils.serialize(user);
FileUtils.writeByteArrayToFile(new File("serialize.txt"), serialize);
}

SerializationUtils是commons-lang3包给我们提供的工具类,它给我们提供了序列化和反序列化的方法,我们直接拿过来用就好了。

FileUtils是commons-io包给我们提供的工具类,它给我们提供了非常丰富的IO操作工具类。

执行方法后,查看serialize.txt:

这就是序列化后,保存到外部的对象了。我们可以把它反序列化成为对象。

反序列化

反序列化代码如下:

@Test
public void deserializeTest() throws IOException {
byte[] bytes = FileUtils.readFileToByteArray(new File("serialize.txt"));
Object object = SerializationUtils.deserialize(bytes);
System.out.println(object instanceof User);
User user = (User)object;
System.out.println(user.getUsername());
}

这里使用FileUtils把外部的文件读入,使用SerializationUtils反序列化成为对象。然后判断反序列化后对象的类型,强转为User后输出其username,运行结果如下:

说明反序列化已经成功过了

修改serialVersionUID值,使反序列化异常

现在把User的serialVersionUID值做一下修改:

@Data
@Builder
public class User implements Serializable { private static final long serialVersionUID = 2L; private String username; }

之前是1,现在改为2,再次执行反序列化方法,结果如下:

这里出现了开头提到的InvalidClassException异常,并且通过异常信息可以看到,这是serialVersionUID不一致引起的。

org.apache.commons.lang3.SerializationException: java.io.InvalidClassException: cn.happy.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

总结

通过理论和代码演示,我们已经知道了serialVersionUID字段可以造成反序列化失败的情况。所以在做系统升级的时候,需要充分考虑是否要改动serialVersionUID的值,因为这会引起兼容性的问题。

为什么阿里Java规约要求谨慎修改serialVersionUID字段的更多相关文章

  1. 为什么阿里Java规约要求谨慎使用SimpleDateFormat

    前言 在阿里Java开发规约中,有强制性的提到SimpleDateFormat 是线程不安全的类 ,在使用的时候应当注意线程安全问题,如下: 其实之前已经介绍过使用JDK1.8的DateTimeFor ...

  2. 为什么阿里Java规约禁止使用Java内置线程池?

    IDEA导入阿里规约插件,当你这样写代码时,插件就会自动监测出来,并给你红线提醒. 告诉你手动创建线程池,效果会更好. 在探秘原因之前我们要先了解一下线程池 ThreadPoolExecutor 都有 ...

  3. 通过java反射机制,修改年龄字段的值

    需求:将生日转为年龄 /** * 获取年龄值 */ public List getAgeInfo(List list) throws Exception { if (null == list || l ...

  4. 点评阿里JAVA手册之编程规约(OOP 规约 、集合处理 、并发处理 、其他)

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文难度系数为三星(★★★) 本文为第二篇 第一篇 点评阿里JAVA手 ...

  5. 阿里Java开发手册1.3.0 文字版

    版本: 1.3.0 update: 2017.9.25 一.编程规约 (一) 命名风格 1. [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例:_name _na ...

  6. 点评阿里JAVA手册之异常日志(异常处理 日志规约 )

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:异常处理 日志规约 本文难度系数为一星(★) 本文为第三篇 ...

  7. 点评阿里JAVA手册之编程规约(命名风格、常量定义、代码风格、控制语句、注释规约)

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文难度系数为一星(★) 码出高效.码出质量. 代码的字里行间流淌的是 ...

  8. 点评阿里JAVA手册之MySQL数据库 (建表规约、索引规约、SQL语句、ORM映射)

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:MySQL数据库 (建表规约.索引规约.SQL语句.ORM映 ...

  9. 阿里Java开发手冊之编程规约

    对于程序猿来说,编程规范能够养成良好的编程习惯,提高代码质量,减少沟通成本.就在2月9号,阿里出了一份Java开发手冊(正式版),分为编程规约.异常日志.MySQL规约,project规约.安全规约五 ...

随机推荐

  1. jquery Ajax标准规范写法

    $.ajax({ url:"http://www.xxx",//请求的url地址 dataType:"json",//返回的格式为json async:true ...

  2. 基于MHA的MYSQL高可用方案

    一.MHA 简介 MHA (Master High Availability )目前在 MySQL 高可用方面是一个相对成熟的解决方案,它由日本 DeNA 公司的 youshimaton 员工(现就职 ...

  3. Spring boot+Thymeleaf传参跳转

    $.ajax(): $.ajax({ type: "get", url:"/public/inform", async: true, data: detailJ ...

  4. 红黑树java代码实现

    红黑树 思想源于:https://www.cnblogs.com/nananana/p/10434549.html有解释有图,很清晰(删除时需考虑根节点和兄弟节点的子节点是否存在) package t ...

  5. Django中url name

    花了好长时间才明白这个name参数的含义.便写下来了备忘 当我们在url的时候,一般情况下都是使用很明确的url地址.如在网页里面使用<a href="/login"> ...

  6. ZOJ4117 BaoBao Loves Reading(2019山东省赛)

    按照计划读书,第i分钟要读第ai本书,起初桌子是空的,所有书都在书架上,如果要读的书不在桌子上,就需要把书从书架上拿到桌子上,如果桌子已经满了,则需要先把桌子上最早读的一本书放回书架,求当桌子容量为k ...

  7. CF10D LCIS 最长公共上升子序列

    题目描述 This problem differs from one which was on the online contest. The sequence a1,a2,...,an a_{1}, ...

  8. 大道至简第一章JAVA伪代码形式读后感

    //愚公移山: public class YuGongYiShan{ //原始需求:“惩山北之塞,出入之迂” //沟通方式:“聚室而谋曰” //项目目标:“毕力平险,指通豫南,达于汉阴” //技术方案 ...

  9. mybatis升级案例之CRUD操作

    mybatis升级案例之CRUD操作 一.准备工作 1.新建maven工程,和入门案例一样 主要步骤如下,可参考mybatis入门实例 a.配置pom.xml文件 b.新建实例类User.DAO接口类 ...

  10. 设计模式课程 设计模式精讲 5-2 工厂方法coding

    1 课堂讲义 1.1 产品等级和产品簇 2 代码演练 2.1 工厂方法代码演练 1 课堂讲义 1.1 产品等级和产品簇 工厂方法是为了解决同一产品等级的业务抽象问题 抽象工厂方法是为了解决同一产品簇的 ...