InvalidClassException异常_原理和解决方案与练习_序列化集合

InvalidClassException异常_原理和解决方案

当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。发生这个异常的原因如下:

该类的序列版本号与从流中读取的类描述符的版本号不匹配
该类包含未知数据类型
该类没有可访问的无参数构造方法
Serializable 接口给需要序列化的类,提供了一个序列版本号。serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。


 

 

序列化运行时使用一个称为serialVersionTD 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和转恢者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的" serialVersionD与对应的发送者的类的版本号不同,则反序列化将会导致InvalidC1assEixceotion。可序列化类可以诵过声明名为“seriaVersionD”的字段〈该字段必须是静态(static)、最终((final)的 long 型字段)显式声明其自己的serialVersionUJID:

 

 

package DemoThreadPool;

import java.io.Serializable;

/**
 * 序列化和反序列化的时候,会抛出NotSerializableException没有序列化异常
 * 类通过实现 java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。Serializable接口也叫标记型接口
 * 要进行序列化和反序列化的类必须实现serializable接口,就会给类添加一个标记当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记
 * 有:就可以序列化和反序列化
 * 没有:就会抛出NotserializabLeException异常
 * 去市场买肉-->肉上有一个蓝色章(检测合格)-->放心购买-->买回来怎么吃随意
 * static关键字:静态关键字
 * 静态优先于非静态加载到内存中(静态优先于对象进入到内存中)被static修饰的成员变量不能被序列化的,序列化的都是对象private static int age;
 * oos.writeobject( new Person("小美女”,18));object o = ois.read0bject();
 * Person{name="小美女',age=
 * transient关键字:瞬态关键字
 * transient关键字:时舜态关键字
 * 被transient修饰成员变量,不能被序列化private transient int age;
 * oos.writeobject( neww Person("“小美女”,18) );object o = ois.read0bject( );
 * Person{name="小美女',age=0}
 */
public class Demo04_Person implements Serializable {
    static final  long serialVersionUID = 42L;
    private String name;
//    private static int age;
//    private transient int age;
public   int age;

    public Demo04_Person() {
    }

    public Demo04_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 "Demo04_Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

package DemoThreadPool;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * java.io.0bjectoutputStream extends outputstreamObjectoutputstream:对象的序列化流
 * 作用:把对象以流的方式写入到文件中保存
 * 构造方法:
 * objectoutputStream(OutputStream out)创建写入指定OutputStream 的 objectOutputStream。参数:
 * outputstream out:字节输出流
 * 特有的成员方法:
 * void write0bject(0bject obj)将指定的对象写入、objectoutputStream。
 * 使用步骤:
 * 1.创建objectoutputstream对象,构造方法中传递字节输出流
 * 2.使用objectoutputstream对象中的方法vriteobject,把对象写入到文件中
 * 3.释放资源
 */
public class Demo04_ObjectStream {
    public static void main(String[] args) throws IOException {
        //1.创建objectoutputstream对象,构造方法中传递字节输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\xiangmu\\jichu\\wenjianjia\\Person.txt"));
        //2.使用objectoutputstream对象中的方法vriteobject,把对象写入到文件中
        oos.writeObject(new Demo04_Person("小明",18));
        //3.释放资源
    }
}
package DemoThreadPool;

import java.io.*;

/*
          java.io.0bjectInputstream extends InputstreamobjectInputstream:对象的反序列化流
作用:把文件中保存的对象,以流的方式读取出来使用
构造方法:
    objectInputStream(InputStream in)创建从指定InputStream 读取的objectInputStream。
 参数:
    InputStream in:字节输入流
特有的成员方法:
    object readobject()从objectInputstream读取对象。
使用步骤:
1.创建objectInputstream对象,构造方法中传递字节输入流
2.使用objectInputstream对象中的方法readobject读取保存对象的文件
3.释放资源
4.使用i读取出来的对象(打印)
 */
public class Demo01_ObjectStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建objectInputstream对象,构造方法中传递字节输入流
        ObjectInputStream oos = new ObjectInputStream(new FileInputStream("G:\\xiangmu\\jichu\\wenjianjia\\Person.txt"));
        //2.使用objectInputstream对象中的方法readobject读取保存对象的文件
        Object o = oos.readObject();
        //3.释放资源
        oos.close();
        //4.使用i读取出来的对象(打印)
        System.out.println(o);
        Demo04_Person p =(Demo04_Person)o;
        System.out.println(p.getName()+p.getAge());
    }
}

序列化集合

当我们想在文件中保存多个对象的时候
可以把多个对象存储到一个集合中
对集合进行序列化和反序列化

分析

1.定义一个存储Person对象的ArrayList集合
2.往ArrayList集合中存储Person对象
3.创建一个序列化流ObjectOutputStream对象
4.使用ObjectOutputStream对象中的方法writeObject,对集合进行序列化
5.创建一个反序列化流ObjectInputStream对象
6.使用ObjectInputStream对象中的方法readObject读取文件中保存的集合
7.把Object类型的集合转换为ArrayList类型
8.遍历ArrayList集合
9.释放资源

 

public class Demo03Text {
    public static void main(String args[]) throws IOException, ClassNotFoundException {
        //1.定义一个存储Person对象的ArrayList集合
        ArrayList<Person> person = new ArrayList<>();
        //2.往ArrayList集合中存储Person对象
        person.add(new Person("夜轻染",18));
        person.add(new Person("容景",17));
        person.add(new Person("苍亭",20));
        //3.创建一个序列化流ObjectOutputStream对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10_IO//list.txt"));
        // 4.使用ObjectOutputStream对象中的方法writeObject,对集合进行序列化
        oos.writeObject(person);
        //5.创建一个反序列化流ObjectInputStream对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day10_IO//list.txt"));
        //6.使用ObjectInputStream对象中的方法readObject读取文件中保存的集合
        Object o = ois.readObject();
        //7.把Object类型的集合转换为ArrayList类型
        ArrayList<Person> list2 = (ArrayList<Person>)o;
        //8.遍历ArrayList集合
        for (Person p : list2) {
            System.out.println(p);
        }
        //9.释放资源
        oos.close();
        ois.close();

    }
}

序列化集合

  1. 将存有多个自定义对象的集合序列化操作,保存到list.txt文件中。
  2. 反序列化list.txt ,并遍历集合,打印对象信息。

案例分析
定义一个存储Person对象的ArrayList集合
往ArrayList集合中存储Person对象
创建一个序列化流ObjectOutputStream对象
使用ObjectOutputStream对象中的方法writeObject,对集合进行序列化
创建一个反序列化ObjectInputStream对象
使用ObjectInputStream对象中的方法readObject读取文件中保存的集合
把Object类型的集合转换为ArrayList类型
遍历ArrayList集合
释放资源

package com.itheima.demo04.ObjectStream;

import java.io.*;
import java.util.ArrayList;


public class Demo03Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("张三",18));
        list.add(new Person("李四",19));
        list.add(new Person("王五",20));
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));
        oos.writeObject(list);
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.txt"));
        Object o = ois.readObject();
        ArrayList<Person> list2 = (ArrayList<Person>)o;
        for (Person p : list2) {
            System.out.println(p);
        }
        ois.close();
        oos.close();
    }
}

 

posted @ 2022-07-14 10:09  zj勇敢飞,xx永相随  阅读(267)  评论(0编辑  收藏  举报