前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么阿里Java规约要求谨慎修改serialVersionUID字段

为什么阿里Java规约要求谨慎修改serialVersionUID字段

作者头像
Happyjava
发布2019-07-16 16:00:07
9860
发布2019-07-16 16:00:07
举报
文章被收录于专栏:Happy的分享Happy的分享

serialVersionUID简要介绍

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

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

阿里Java规约中的描述

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

代码演示

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

引入依赖
代码语言:javascript
复制
<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如下:

代码语言:javascript
复制
@Data
@Builder
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private String username;

}
复制代码

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

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

序列化代码:

代码语言:javascript
复制
@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:

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

反序列化

反序列化代码如下:

代码语言:javascript
复制
@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值做一下修改:

代码语言:javascript
复制
@Data
@Builder
public class User implements Serializable {

    private static final long serialVersionUID = 2L;

    private String username;

}
复制代码

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

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

代码语言:javascript
复制
org.apache.commons.lang3.SerializationException: java.io.InvalidClassException: cn.happy.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
复制代码

总结

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年06月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • serialVersionUID简要介绍
  • 阿里Java规约中的描述
  • 代码演示
  • 总结
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档