上一篇博客介绍了因为不可串行化导致的异常处理,是因为在实体类没有实现Serializable所导致的,这篇博客的目的是介绍一下序列化号异常的处理,是对上一篇博客的深入解答,实体类还是原来的那个实体类,如下:
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private int age;
// private static int age; // 静态内容不会保存
// private transient int age; // transient内容不会保存
// transient: 瞬态
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
此时,boss让我们在试题里面增加一个人的地址:private String address;然后在我查看原来文件存储的内容的时候,给我报出了如下的错误:
"D:\Program Files\Java\jdk-9.0.1\bin\java" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2017.3.2\lib\idea_rt.jar=60416:D:\Program Files\JetBrains\IntelliJ IDEA 2017.3.2\bin" -Dfile.encoding=UTF-8 -classpath F:\out\production.Class.Demo10ObjectInputStream对象反序列化流.Demo10 Exception in thread "main" java.io.InvalidClassException: com.Demo09ObjectOutputStream对象序列化流.Person; local class incompatible: stream classdesc serialVersionUID = -2309631243571516114, local class serialVersionUID = -1485624930095365046 at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689) at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1898) at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1764) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2055) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1586) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:423) at com.itheima.Day11.Class.Demo10ObjectInputStream对象反序列化流.Demo10.main(Demo10.java:23)
这是什么鬼,而且还这么多内容,啥子情况。
根据上一篇博客的分析思路来解答,
Exception in thread "main" java.io.InvalidClassException
这个异常是说在主方法处抛出无效的类异常,如果熟悉的朋友立马就知道是哪里出错了,不熟悉的朋友没关系,这篇博客的目的就是详细讲解出现这个异常的原因。
读取内容的代码如下:
因为这篇博客是上一篇博客的延伸,所以套用上一篇博客的代码,实体类的代码就在上面的前言部分。
ObjectOutputStream的代码如下:
public static void main(String[] args) throws IOException {
Person p1 = new Person("孙悟空",18);
FileOutputStream fos = new FileOutputStream("F:\\src\\com\\Test\\Demo09.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p1);
oos.close();
}
ObjectInputStream端的代码如下:
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\src\\com\\Test\\Demo09.txt"));
Object obj = ois.readObject();
System.out.println(obj);
ois.close();
}
为什么会出现无效的类异常呢?是因为之前我说了,在实体类里面增加/减少了一些属性,而导致的,原因有下面几条。
在修改完实体类之后,没有通过ObjectOutputStream进行编译,那么原来的那个文件所使用实体的序列号和现在修改了属性重新生成实体的序列号不匹配,所以,错误中会有这么一段:
Exception in thread "main" java.io.InvalidClassException: com.Demo09ObjectOutputStream对象序列化流.
Person; local class incompatible:
stream classdesc serialVersionUID = -2309631243571516114,
local class serialVersionUID = -1485624930095365046
从上面罗列出的代码可以看出,一个UID是:-2309631243571516114,而另一个UID是:-1485624930095365046,完全匹配不上,所以就报错了。具体请见下图:
通过上面图就可以很好的理解为什么会产生错误了。
既然是实体类的序列化号出现了错误,随机产生了另外的一组编号,那么我们就可以给类指定序列化号,具体方法是在实体类中写入如下方法:
private static final long serialVersionUID = 110L;
当然,UID的序列化号可以随意定义,但最好是定义成为我们简单易懂的更好。
在对象序列化流当中有很多的技巧需要我们好好的取研究,所以这方面的学习是非常值得我们深深的思考,没事的时候可以去看看源码,能给我们很多的提示。
谢谢您的阅读!