面试题答案
一键面试- 通过
serialVersionUID
优化序列化配置保证对象版本兼容性的方法:- 手动声明
serialVersionUID
:在可序列化类中显式声明一个private static final long serialVersionUID
字段。这样,即使类的结构发生了一些变化(如添加或删除非关键字段等),只要serialVersionUID
不变,Java序列化机制就会认为这两个版本的类是兼容的,可以进行序列化和反序列化操作。
- 手动声明
- 不同取值可能带来的影响:
- 取值相同:
- 示例:
假设后续对import java.io.Serializable; public class VersionedClass implements Serializable { private static final long serialVersionUID = 1L; private String name; public VersionedClass(String name) { this.name = name; } public String getName() { return name; } }
VersionedClass
类进行了一些小改动,比如添加一个新的private int age;
字段,但是serialVersionUID
仍保持为1L
。import java.io.Serializable; public class VersionedClass implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public VersionedClass(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
- 影响:在这种情况下,使用旧版本类序列化的对象可以在新版本类中成功反序列化。对于新添加的字段
age
,反序列化时会使用其默认值(int
类型为0
)。这保证了版本兼容性,使得系统在类结构演进时不需要重新处理已序列化的数据。
- 示例:
- 取值不同:
- 示例:
然后修改类并改变import java.io.Serializable; public class VersionedClass implements Serializable { private static final long serialVersionUID = 1L; private String name; public VersionedClass(String name) { this.name = name; } public String getName() { return name; } }
serialVersionUID
的值。import java.io.Serializable; public class VersionedClass implements Serializable { private static final long serialVersionUID = 2L; private String name; private int age; public VersionedClass(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
- 影响:如果尝试用新版本类(
serialVersionUID
为2L
)去反序列化使用旧版本类(serialVersionUID
为1L
)序列化的对象,会抛出InvalidClassException
异常,因为serialVersionUID
不匹配,Java序列化机制认为这是两个不兼容的类版本,无法进行反序列化操作。这有助于在类结构发生重大变化时,防止错误地反序列化旧数据,避免潜在的运行时错误。
- 示例:
- 取值相同: