InvalidClassException:无效类异常

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版权协议,转载请附上原文出处链接和本声明。