对Java对象序列化serialVersionUID的理解

serialVersionUID按字面上意思来理解是序列化版本号,用以下例子可以得出serialVersionUID的实际作用

Person类:

public class Person implements Serializable{
 
private String name;
private int age;
 
public Person(String name, int age) {
this.name = name;
this.age = age;
}
 
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}

Test测试类:

public class Test {
 
public static void main(String[] args) {
try {
Serialize();
Person person = Deserialize();
System.out.println(person);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void Serialize() throws FileNotFoundException, IOException{
Person person = new Person("jack", 25);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:person.txt"));
oos.writeObject(person);
System.out.println("Person类序列化成功");
oos.flush();
oos.close();
}
private static Person Deserialize() throws FileNotFoundException, IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:person.txt"));
Person person = (Person) ois.readObject();
System.out.println("Person类反序列化成功");
ois.close();
return person;
}
}



①在Person类没有添加serialVersionUID时,先执行Serialize()方法,运行结果:

Person类序列化成功

②在Person新加sex属性:

public class Person implements Serializable{
 
private String name;
private int age;
private String sex;
 
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
 
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
 
}

③这时候再执行Deserialize()方法,抛出异常:

java.io.InvalidClassException: one.Person; local class incompatible: stream classdesc serialVersionUID = -933002983885753244,
 local class serialVersionUID = -3251846478824884491
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at one.Test.Deserialize(Test.java:33)
at one.Test.main(Test.java:15)

意思就是说,文件流中的class和classpath中的class,也就是修改过后的class,不兼容了,处于安全机制考虑,程序抛出了错误,并且拒绝载入。

可以看到,我们在Person类中没有指定Person类的serialVersionUID属性,所以java编译器会自动给这个class进行一个摘要算法,类似于指纹算法,只要这个文件 多一个空格,得到的UID就会截然不同的,这样子就可以保证在这么多类中,这个编号是唯一的。

总的来说,serialVersionUID属性相当于Java对象的序列化版本号(类似于人类指纹),编译器会根据这个值来判断能否反序列化,在我们没指定对象的serialVersionUID属性时,对象也会有一个自动生成的serialVersionUID属性。

因此,如果我们需要对象在序列化后改变不影响反序列化,就必须指定实体类的serialVersionUID属性。

修改后的Person类:

public class Person implements Serializable{
 
private static final long serialVersionUID = -3251846478824884491L;
 
private String name;
private int age;
private String sex;
 
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
 
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}

程序运行结果:

Person类序列化成功
Person类反序列化成功
Person [name=jack, age=25, sex=男]


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值