序列化的坑
● 实体类的信息需要持久化,实现了接口serializable,但没有指定值private static final long serialVersionUID;在之后使用的时候文件在服务器上但即使读取不到。
serializable 是一个标记,java中药序列化必须实现这个接口;不默认实现可能是为了安全
public class StageInfo implements Serializable {
/**
* stage 排序编号,从0开始
**/
private Integer number;
/**
* stage ID
**/
private String id;
...
}
//读取文件信息,很老的代码了
public static <E> List<E> readObjectForList(String filePath) {
E [] object;
File file = new File(filePath);
if (file.exists()) {
try(ObjectInputStream out = new ObjectInputStream(new FileInputStream(file))) {
object = (E[]) out.readObject();
return Arrays.asList(object);
}
catch (IOException e) {
log.error("文件解析失败" + e.getMessage());
e.printStackTrace();
}
catch (ClassNotFoundException e) {
log.error("文件解析失败" + e.getMessage());
e.printStackTrace();
}
}
return null;
}
- 经看日志发现异常java.io.InvalidClassException,这是序列化相关异常
加上private static final long serialVersionUID = 2531697581628090341L;后读取日志报错如下
- 文件解析失败cn.harmonycloud.pipeline.stageandstep.entity.StageParallelInfo; local class incompatible: stream classdesc serialVersionUID = -7979539792943633706, local class serialVersionUID = 1957675234537638335
java.io.InvalidClassException: cn.harmonycloud.pipeline.stageandstep.entity.StageParallelInfo; local class incompatible: stream classdesc serialVersionUID = -7979539792943633706, local class serialVersionUID = 1957675234537638335
由于序列化id不同已经读不到了。
复盘
● 如果不加serialVersionUID,也能进行持久化因为系统会默认生成一个id,但是当类发生变化或者编译器发生变化,默认的id会改变就会导致反序列化失败。
● serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。
● 类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。