叙述

今天在写项目时遇到了一个问题,我有一个类因为需求需要添加一个新的字段信息,当我在该l类上添加这个字段后,测试接口获取这个类对象的信息时,给我报了一个序列化错误的Excption,具体错误信息如下
在这里插入图片描述

原因

通过错误日志,我们可以很清楚的了解到造成异常的原因主要就是serialVersionUID不对应导致的。
这个问题其实主要还是我们平时不规范的编码方式造成的,我们知道serialVersionUID的作用是,保证对象在序列化时版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
如果我们的类实现了Serializable接口,我们就需要给该类指定一个serialVersionUID,保证对象在序列化和反序列化都能保证一致。通常的做法是

private static final long serialVersionUID = 1L;

当然如果你没有在该类中显示的设置serialVersionUID的话
JVM会根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段作为该类的serialVersionUID。
而我目前就是没有显示的设置serialVersionUID, 而又因为我使用了redis做数据缓存,并且在还没有更改该类之前已经做了一次请求,并完成了数据缓存。当我在该类中新增了一个字段后,随着成员属性的变化,serialVersionUID也跟着改变了,而这时候redis中缓存的数据对象在序列化时所使用的serialVersionUID是上一个版本的,所以redis中的数据对象在反序列化时发现serialVersionUID不匹配而导致失败,抛出java. io. InvalidClassException异常。

解决办法

解决的办法有两种

  1. 如果不打算兼容redis中的老数据,那可以在类中指定 serialVersionUID = 1L,然后删除掉redis中的老数据。
  2. 如果打算兼容老数据,可以在类中指定serialVersionUID的值为redis中老数据对象的serialVersionUID的值,这个值会在错误日志中得出。
总结

因为我们目前所写的项目都是单体系统,项目在每次重启之后都会重新实例化对象,而很少会用到对象的序列化和反序列化的机制,因此我们即时不指定serialVersionUID也不会报java. io. InvalidClassException异常。而因为这样我们往往很容易或略掉这个serialVersionUID的指定,这不是一个好的编码习惯,当我们需要用到对象的序列化和反序列化机制时,如果我们没有指定serialVersionUID, 而在对象被序列化之后,我们改了类信息,那么类的默认serialVersionUID也跟着改变,当我们把之前序列化的对象进行反序列化时就会因为serialVersionUID不匹配而报错。所以建议大家在编码过程中如果某个类实现了Serializable接口,就给指定一个serialVersionUID。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐