Java 之 ObjectInputStream 类

ObjectInputStream 类

  1、概述

      java.io.ObjectInputStream extends InputStream

    ObjectInputStream 反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象,以流的方式读取对象。 

  2、构造方法

ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。

    参数:InputStream in:字节输入流

  3、特有的成员方法

Object readObject() 从 ObjectInputStream 读取对象。

  

  4、使用步骤

    ① 创建ObjectInputStream对象,构造方法中传递字节输入流

    ② 使用ObjectInputStream对象中的方法readObject读取保存对象的文件

    ③ 释放资源

    ④ 使用读取出来的对象(打印)

  5、注意

     readObject方法声明抛出了ClassNotFoundException(class文件找不到异常)

    当不存在对象的 class 文件时抛出此异常:

    反序列化的前提:

      ① 类必须实现 Seriaizable 

      ② 必须存在类对应的 class 文件

  6、反序列化操作1

    如果能找到一个对象的class文件,可以进行反序列化操作,调用 ObjectInputStream 读取对象的方法:

public final Object readObject () : 读取一个对象。

      Demo:

 1 public static void main(String [] args) {
 2     Employee e = null;
 3     try {
 4         // 创建反序列化流
 5         FileInputStream fileIn = new FileInputStream("employee.txt");
 6         ObjectInputStream in = new ObjectInputStream(fileIn);
 7         // 读取一个对象
 8         e = (Employee) in.readObject();
 9         // 释放资源
10         in.close();
11         fileIn.close();
12     }catch(IOException i) {
13         // 捕获其他异常
14         i.printStackTrace();
15        return;
16     }catch(ClassNotFoundException c) {
17         // 捕获类找不到异常
18         System.out.println("Employee class not found");
19         c.printStackTrace();
20         return;
21     } 
22         // 无异常,直接打印输出
23     System.out.println(e); 
24 
25     }
26 }

  对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个ClassNotFoundException 异常。

  7、反序列化操作2

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

    原因如下

      ① 该类的序列版本号与从流中读取的类描述符的版本号不匹配

      ② 该类包含未知数据类型

      ③ 该类没有可访问的无参数构造方法

    Serializable 接口给需要序列化的类,提供了一个序列版本号serialVersionUID 该版本号的目的在于验证序
列化的对象和对应类是否版本匹配。

    Demo:

 1 public class Employee implements java.io.Serializable {
 2     // 加入序列版本号
 3     private static final long serialVersionUID = 1L;
 4     public String name;
 5     public String address;
 6     // 添加新的属性 ,重新编译, 可以反序列化,该属性赋为默认值.
 7     public int eid;
 8     public void addressCheck() {
 9         System.out.println("Address check : " + name + " ‐‐ " + address);
10     }
11 }

   序列号冲突异常的原理和解决方案:

猜你喜欢

转载自www.cnblogs.com/niujifei/p/11499141.html