首页 > 试题广场 >

Serializable接口为什么需要定义serialVer

[问答题]

Serializable接口为什么需要定义serialVersionUID常量

推荐

得分点

​ 兼容性、自定义

参考答案

标准回答

​ serialVersionUID是序列化版本,为一个类定义序列化版本,是出于兼容性的考虑。如果某个类随着项目进行了升级,那么对于升级之前序列化的数据,在升级之后反序列化时就很可能出现不兼容的情况。如果事先定义了序列化的版本,则在反序列化的时候,只要版本不变就可以将其认定为同一个class文件。Java采用以下的形式来定义序列化版本:

private static final long serialVersionUID = ...;

​ 需要注意的是,如果没有显示定义serialVersionUID,则JVM会根据类的信息自动计算出它的值,如果升级前后类的内容发生了变化,该值的计算结果通常就不同,这会导致反序列化的失败。所以,最好在打算序列化的类中显示地定义serialVersionUID,这样即便在序列化后它对应的类被修改了,由于版本号是一致的,所以该对象依然可以被正确的反序列化。

加分回答

​ 如果类的修改会导致反序列化失败,则应该为此类分配新的serialVersionUID,那么对类的哪些内容进行修改会导致反序列化失败呢?

  1. 如果修改类时只是修改了方法,则反序列化不受影响。
  2. 如果修改类时只是修改了静态变量,则反序列化不受影响。
  3. 如果修改类时改变了实例变量,则可能导致反序列化失败。

延伸阅读

​ 序列化版本的示例:

/**
 * 序列化的版本
 */
public class IODemo12 {

    public static void main(String[] args) {
        testSerialize();
        testDeserialize();
    }

    public static void testSerialize() {
        try (
                ObjectOutputStream oos = new ObjectOutputStream(
                        new FileOutputStream("C:/work/alpha/dri.txt"));
        ) {
            Driver d = new Driver("Tom", 'M', 23);
//            d.setLicense("H0527");
//            d.setLevel(5);
            oos.writeObject(d);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void testDeserialize() {
        try (
                ObjectInputStream ois = new ObjectInputStream(
                        new FileInputStream("C:/work/alpha/dri.txt"));
        ) {
            Driver d = (Driver) ois.readObject();
            System.out.println(d);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

class Driver implements Serializable {

    private static final long serialVersionUID = 847704670584248289L;
    private String name;
    private char gender;
    private int age;
    private String licenseNO; // license -> licenseNO
    //    private int level;
    private int order;

    public Driver(String name, char gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getLicenseNO() {
        return licenseNO;
    }

    public void setLicenseNO(String licenseNO) {
        this.licenseNO = licenseNO;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public String toString() {
        return "Driver{" +
                "name='" + name + '\'' +
                ", gender=" + gender +
                ", age=" + age +
                ", licenseNO='" + licenseNO + '\'' +
                ", order=" + order +
                '}';
    }
}
编辑于 2021-09-15 10:41:50 回复(0)

serialVersionUID常量用于标明当前Serializable类的版本,以验证加载的类和序列化对象是否兼容。

在进行序列化时会将当前类的serialVersionUID写入到字节序列中,在反序列化时会将当前字节流中的serialVersionUID同本地对象中的serialVersionUID进行对比,如果相同则继续序列化,如果不同则失败报错。

serialVersionUID常量值默认为1L。

发表于 2022-06-28 17:18:18 回复(0)

序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException

编辑于 2023-12-02 19:37:11 回复(0)

serialVersionUID常量用于标明当前Serializable类的版本,以验证加载的类和序列化对象是否兼容。

在进行序列化时会将当前类的serialVersionUID写入到字节序列中,在反序列化时会将当前字节流中的serialVersionUID同本地对象中的serialVersionUID进行对比,如果相同则继续序列化,如果不同则失败报错。

serialVersionUID常量值默认为1L

发表于 2022-09-04 21:43:26 回复(0)
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException
发表于 2022-12-31 12:38:20 回复(0)
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException
发表于 2021-10-21 00:29:16 回复(0)