为什么阿里Java规约要求谨慎修改serialVersionUID字段
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字段的更多相关文章
- 为什么阿里Java规约要求谨慎使用SimpleDateFormat
前言 在阿里Java开发规约中,有强制性的提到SimpleDateFormat 是线程不安全的类 ,在使用的时候应当注意线程安全问题,如下: 其实之前已经介绍过使用JDK1.8的DateTimeFor ...
- 为什么阿里Java规约禁止使用Java内置线程池?
IDEA导入阿里规约插件,当你这样写代码时,插件就会自动监测出来,并给你红线提醒. 告诉你手动创建线程池,效果会更好. 在探秘原因之前我们要先了解一下线程池 ThreadPoolExecutor 都有 ...
- 通过java反射机制,修改年龄字段的值
需求:将生日转为年龄 /** * 获取年龄值 */ public List getAgeInfo(List list) throws Exception { if (null == list || l ...
- 点评阿里JAVA手册之编程规约(OOP 规约 、集合处理 、并发处理 、其他)
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文难度系数为三星(★★★) 本文为第二篇 第一篇 点评阿里JAVA手 ...
- 阿里Java开发手册1.3.0 文字版
版本: 1.3.0 update: 2017.9.25 一.编程规约 (一) 命名风格 1. [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例:_name _na ...
- 点评阿里JAVA手册之异常日志(异常处理 日志规约 )
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:异常处理 日志规约 本文难度系数为一星(★) 本文为第三篇 ...
- 点评阿里JAVA手册之编程规约(命名风格、常量定义、代码风格、控制语句、注释规约)
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文难度系数为一星(★) 码出高效.码出质量. 代码的字里行间流淌的是 ...
- 点评阿里JAVA手册之MySQL数据库 (建表规约、索引规约、SQL语句、ORM映射)
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:MySQL数据库 (建表规约.索引规约.SQL语句.ORM映 ...
- 阿里Java开发手冊之编程规约
对于程序猿来说,编程规范能够养成良好的编程习惯,提高代码质量,减少沟通成本.就在2月9号,阿里出了一份Java开发手冊(正式版),分为编程规约.异常日志.MySQL规约,project规约.安全规约五 ...
随机推荐
- Spring的事务实现原理
主流程 Spring的事务采用AOP的方式实现. @Transactional 注解的属性信息 name 当在配置文件中有多个 TransactionManager , ...
- 【MySQL】索引相关
" 目录 普通索引 唯一索引 主键索引 组合索引 正确使用索引的情况 索引的注意事项 执行计划 axplain 慢日志记录 分页性能相关方案 索引是数据库中专门用于帮助用户快速查找数据的一种 ...
- bitnami-redmine 一键安装
下载bitnami-redmine https://bitnami.com/stack/redmine 安装 选择语言 设置登陆用户名和密码,数据库用户名root,数据库密码也是这个设置的密码 其他下 ...
- Linux - Shebang(#!)
1. Shebang这个符号通常在Unix系统的脚本中第一行开头中写到,它指明了执行这个脚本文件的解释程序.
- Stream:java1.8新特性
原 Stream:java1.8新特性 2017年08月01日 18:15:43 kekeair-zhang 阅读数:392 标签: streamjava1-8新特性 更多 个人分类: 日记 版权声明 ...
- xml配置问题--------不允许有匹配 "[xX][mM][lL]" 的处理指令目标
剪不断,理还乱,是BUG 相遇:不允许有匹配 "[xX][mM][lL]" 的处理指令目标 在编写MyBatic框架时,纯手编写mybatic-config.xml文件,遇 ...
- Linux 常用命令——查看系统
有的时候别人给你一个登录方式,但是不知道是啥系统,看图就知道了 1.uname -a 查看电脑以及操作系统 2.cat /proc/version 正在运行的内核版本 3.cat /etc/is ...
- MySQL复制方法
MySQL的二进制日志,MySQL复制原理,MySQL主从模式搭建,MySQL双主模式搭建,MySQL级联模式搭建,MySQL半同步模式复制 一.二进制日志 1.概念 MySQL的二进制日志(bina ...
- 的aspnet_client文件夹
在早期,有一些asp.net组件是默认要调用(从客户端调用)服务器根(域名)下这个子目录里边的文件的. 不过如果你使用高版本的asp.net,那么全都从你的网站里调用了,因为asp.net有了更好地直 ...
- leetCode练题——20. Valid Parentheses
1.题目 20. Valid Parentheses——Easy Given a string containing just the characters '(', ')', '{', '}', ...