InvalidClassException:无效类异常
在第一次读取的时候没有报错,直接输出Person对象的时候,打印的是地址值,看得不是很方便,所以我在Person重写了toString方法此时报错了。
InvalidClassException: com.ginger.demo01.Person;
local class incompatible: stream classdesc serialVersionUID = 311183030272692197, local class serialVersionUID = 6499259360078010285
为什么第一次读取不出现异常,在Person重写toString方法的时候在读取,就出现上述异常?
原因:Person类实现了序列化接口Serializable,那么它本身也因该有一个标记值。
假设该标记值为1000。
Person.class -- 序列化id=1000 (把java文件编译成class文件)
writer数据 -- oos.txt -- 序列化id该是=1000
read数据 -- oos.txt -- 反序列化id也是=1000
所以我第一次读取的时候没有抛出异常
因为输出的是地址值,重写Person的toString方法,也正是因为修改了Person方法。
Person.class -- 此时序列化id=2000 (把java文件重新编译成class文件)
writer数据 -- oos.txt -- 因为还是以前的文件,序列化id就是=1000 (此时的writer方法我已经注释了,没有重新写到文件)
read数据 -- oos.txt -- 所以读取的也还是以前的文件,序列化就是=1000
出现该异常要怎么解决?
修改Person过后,重新写文件,重新读文件。(这样有一个问题,就是以前读的数据被覆盖了?)
在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?
通过异常信息可以看出来,报错原因是因为id值不匹配,每次修改java文件内容的时候,class文件的id值就会发生改变。而读取文件的时候,会和class
文件中的id进行匹配。所以就会出问题。
如果我有办法,让这个id值在java文件中是一个固定的值,这样,在修改java文件的时候,这个id值就不会发生改变了。
怎么获取到这个ID值呢?
eclipse:实现序列化接口的时候会出现一个黄色警告线,点击提示中的两个其中一个即可。
在IDEA里面需要安装一个插件,这个在网上找就可以了。安装好后使用快捷键Alt+insert就可以了,自动生成。
private static final long serialVersionUID = 6499259360078010285L;
要知道的是:
序列化id:private static final long serialVersionUID = 6499259360078010285L;
产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。(读取还是以前的信息,不是改变过后的。)
注意:
我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?
使用transient关键字声明不需要序列化的成员变量
代码演示
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写
//writer();
//读
reader();
}
public static void reader() throws IOException, ClassNotFoundException {
//创建反序列化流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
//oos.txt--流数据--对象
Object p = ois.readObject();
System.out.println(p);
}
public static void writer() throws IOException {
//创建序列化流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
//创建Perion对象
Person p = new Person("格雷福斯", 40,"100");
//对象--流数据--oos.txt
oos.writeObject(p);
oos.close();
}
}
实体类
public class Person implements Serializable {
//自动生成序列化id
private static final long serialVersionUID = 6499259360078010285L;
private String name;
private int age;
private String chinese;
public String getChinese() {
return chinese;
}
public void setChinese(String chinese) {
this.chinese = chinese;
}
public Person(String name, int age, String chinese) {
this.name = name;
this.age = age;
this.chinese = chinese;
}
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 +
", chinese='" + chinese + '\'' +
'}';
}
}
结果:
Person{name='格雷福斯', age=40, chinese='100'}
修改实体类,chinese这个字段我不想被序列化,重新写读。
public class Person implements Serializable {
//自动生成序列化id
private static final long serialVersionUID = 6499259360078010285L;
private String name;
private int age;
//transient:chinese我不想被序列化
private transient String chinese;
public String getChinese() {
return chinese;
}
public void setChinese(String chinese) {
this.chinese = chinese;
}
public Person(String name, int age, String chinese) {
this.name = name;
this.age = age;
this.chinese = chinese;
}
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 +
", chinese='" + chinese + '\'' +
'}';
}
}
结果:从结果看到chinese值已经看不到了
Person{name='格雷福斯', age=40, chinese='null'}
版权声明:本文为qq_40332952原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。