实例变量已更改的Java反序列化

实例变量已更改的Java反序列化,java,deserialization,Java,Deserialization,我使用私有静态final long serialVersionUID=1L序列化一个学生类并对其进行反序列化。当我更改学生类的实例变量并对其进行反序列化时,假设我将name实例变量更改为fullName,并在不序列化此修改的学生类的情况下调用反序列化。 我仍然可以做下面的cast-in-deserialse方法 Student stud=(Student)ois.readObject() 为什么它在强制转换期间不抛出任何异常,因为传入的反序列化类和新修改的类是不同的。此外,所有保持未修改的实例变

我使用私有静态final long serialVersionUID=1L序列化一个学生类并对其进行反序列化。当我更改学生类的实例变量并对其进行反序列化时,假设我将name实例变量更改为fullName,并在不序列化此修改的学生类的情况下调用反序列化。 我仍然可以做下面的cast-in-deserialse方法

Student stud=(Student)ois.readObject()

为什么它在强制转换期间不抛出任何异常,因为传入的反序列化类和新修改的类是不同的。此外,所有保持未修改的实例变量在反序列化后都恢复了值,但修改的实例变量除外。 然而,当我从学生类中删除私有静态final long serialVersionId=1L并进行反序列化时,我得到了java.io.InvalidClassException,这是可以理解的。 所以当serialVersionUID匹配时,它不检查类的任何其他属性吗? 这背后的概念是什么

    class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int id;
public String name() {
    return name;
}
public void setname(String name) {
    this.name = name;
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
}

不是检查字段的状态(=值),而是使用serialVersionUID检查类定义(=类上有哪些字段可用)。SerialVersionUID是一个可选字段。如果不定义一个,JVM将为您生成一个。因此,如果您有一个值为1L的序列化类,并尝试使用生成的类(例如-687991492884005033L)对其进行反序列化,则将导致InvalidClassException

从Java文档中:

序列化运行时与每个可序列化类关联 版本号,称为serialVersionUID,在 反序列化以验证序列化的发送方和接收方 对象已为该对象加载与兼容的类 关于序列化。如果接收器已为 对象的SerialVersionId与的SerialVersionId不同 对应发件人的类,则反序列化将导致 InvalidClassException。可序列化类可以声明自己的类 通过声明名为 “serialVersionUID”必须是静态的、最终的且类型为long:

ANY-ACCESS-MODIFIER静态最终长serialVersionUID=42L

如果可序列化类未显式声明serialVersionUID, 然后序列化运行时将计算默认值 该类的SerialVersionId值基于 类,如Java(TM)对象序列化中所述 规范。但是,强烈建议: 可序列化类显式声明serialVersionUID值,因为 默认的serialVersionUID计算对类高度敏感 详细信息可能因编译器实现而异,可以 因此,在运行期间会导致意外的InvalidClassException 反序列化

关于SerialVersionUID计算的一个非常相关的答案是:;

不是检查字段的状态(=值),而是使用serialVersionUID检查类定义(=类上可用的字段)。SerialVersionUID是一个可选字段。如果不定义一个,JVM将为您生成一个。因此,如果您有一个值为1L的序列化类,并尝试使用生成的类(例如-687991492884005033L)对其进行反序列化,则将导致InvalidClassException

从Java文档中:

序列化运行时与每个可序列化类关联 版本号,称为serialVersionUID,在 反序列化以验证序列化的发送方和接收方 对象已为该对象加载与兼容的类 关于序列化。如果接收器已为 对象的SerialVersionId与的SerialVersionId不同 对应发件人的类,则反序列化将导致 InvalidClassException。可序列化类可以声明自己的类 通过声明名为 “serialVersionUID”必须是静态的、最终的且类型为long:

ANY-ACCESS-MODIFIER静态最终长serialVersionUID=42L

如果可序列化类未显式声明serialVersionUID, 然后序列化运行时将计算默认值 该类的SerialVersionId值基于 类,如Java(TM)对象序列化中所述 规范。但是,强烈建议: 可序列化类显式声明serialVersionUID值,因为 默认的serialVersionUID计算对类高度敏感 详细信息可能因编译器实现而异,可以 因此,在运行期间会导致意外的InvalidClassException 反序列化

关于SerialVersionUID计算的一个非常相关的答案是:;

以下是引用的,应该可以回答您的问题

粗体部分与您的示例非常相关

…想象你创建一个类,实例化它, 并将其写入对象流。那个扁平的物体在里面 一段时间以来,文件系统一直在运行。同时,更新类文件, 可能会添加一个新字段。当你试着在书中阅读时会发生什么 扁平物体

好吧,坏消息是将抛出一个异常-- 具体来说,java.io.InvalidClassException——因为 具有持久性功能的类将自动获得唯一的 标识符如果类的标识符不等于 展平对象的标识符,将引发异常。 然而,如果你真的想一想,为什么要把它扔掉呢 因为我加了一个字段?该字段不能设置为默认值吗 值,然后下次再写出来

是的,但是需要一些代码操作。T