最近刚好在打java基础,但是用ObjectOutputStream进行反序列的时候
遇到了反序列化失败的问题,所以在这里讨论一下反序列化失败的问题
java.io.InvalidClassException: javaSE.bean.Student; local class incompatible: stream classdesc serialVersionUID = -4563547663326088190, local class serialVersionUID = -27206582129922100
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2001)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459)
异常信息:
很明显抛出异常的原因就是:
本地类的序列化版本号和我们进行序列化时的序列化版本号不同
所以要搞清楚这个异常就要搞清楚序列化版本号是个什么东西
我们在进行序列化的时候会让某个类去实现serializable接口
比如我有一个student类去实现serializable接口:
public class Student implements Serializable {
private int age;
private String name;
public Strudent(int age, String name){
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
读到这里你肯定对序列化版本号多少有点了解了,下面是对序列化版本号的具体说明
在讲清楚序列化版本号之前,我们来看个故事:
public class Student implements Serializable {
private int age;
private String name;
public Strudent(int age, String name){
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
三年后,小蓝跑路了。来了个新人小红,由于业务需求,小红在小蓝写的类上增加了一个id属性
public class Student implements Serializable {
private int age;
private String name;
private int id;
public Student(int age, String name, int id) {
this.age = age;
this.name = name;
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", id=" + id +
'}';
}
}
当小红改完代码,重新运行程序时,项目跑不了,抛出的异常让小红懵逼了
java.io.InvalidClassException: javaSE.bean.Student; local class incompatible: stream classdesc serialVersionUID = -4563547663326088190, local class serialVersionUID = -27206582129922100
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2001)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459)
小红请教了她的师傅,师傅告诉她:加一个序列化版本号就行了
小红照做了:
public class Student implements Serializable {
private static final long serialVersionUID = 7471391170055841173L;
private int age;
private String name;
private int id;
public Student(int age, String name, int id) {
this.age = age;
this.name = name;
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", id=" + id +
'}';
}
}
对于序列化版本号的并没有多大讲究,
在实现了serializable接口的类中添加一个serialVersionUID即可
只要保证在一个项目中序列化版本号不要重复就行
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 7471391170055841173L;