Java IO: ObjectInputStream 类

在 Java 中,ObjectInputStream 类(java.io.ObjectInputStream)可让您从 InputStream 中读取 Java 对象,而不仅仅是原始字节。将 InputStream 封装在 ObjectInputStream 中,然后就可以从中读取对象。

image.png

注意:

(1)读取的字节必须是有效的、序列化的 Java 对象,否则读取对象将失败。

(2) 通常,你将使用 ObjectInputStream 来读取由 ObjectOutputStream 写入(序列化)的对象。

ObjectInputStream 示例

以下是一个 ObjectInputStream 示例:

ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("object.data"));
MyClass object = (MyClass) objectInputStream.readObject();
//...
objectInputStream.close();

注意,要使这个 ObjectInputStream 示例有效,你读取的对象必须是 MyClass 的实例,并且必须已通过 ObjectOutputStream 序列化到文件“object.data ”中。

在序列化和反序列化对象之前,对象的类必须实现 java.io.Serializable 接口。

Serializable 接口

Serializable 是一个标记接口(Marker Interface),标记接口的特点是接口内部没有定义任何方法。其存在的意义在于给类打上一个 “标记”,告知 Java 虚拟机(JVM)这个类的对象可以被序列化。

Serializable 接口源码:

public interface Serializable {
}

序列化和反序列化

序列化

序列化指的是把 Java 对象转换为字节序列的过程。这些字节序列能够被存储在文件中,也可以通过网络进行传输。

反序列化

与序列化相反,它是把字节序列重新转换为 Java 对象的过程。

注意,我们可以通过 ObjectInputStream 类实现反序列化,通过 ObjectOutputStream 类实现序列化。

ObjectInputStream 与 ObjectOutputStream 结合使用

下面将展示一个将 ObjectInputStream 与 ObjectOutputStream 结合使用的示例。演示如何对 Java 对象进行序列化和反序列化,如下:

package com.hxstrive.java_io;

import java.io.*;

public class ObjectInputStreamExample {
    public static void main(String[] args) throws Exception {
        // 序列化
        try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.data"))) {
            Person person = new Person(1, "张三");
            out.writeObject(person);
        }

        // 反序列化
        try(ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.data"))) {
            Person person = (Person)in.readObject();
            System.out.println(person); // 输出:Person{id=1, name='张三'}
        }
    }

    // 实现了 Serializable 标记接口
    static class Person implements Serializable {
        private int id;
        private String name;

        public Person(int id, String name) {
            this.id = id;
            this.name = name;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
}

上面示例,首先创建了一个与 FileOutputStream 相连的 ObjectOutputStream,接着创建一个 Person 对象并将其写入 ObjectOutputStream,即 object.data 文件。

然后,创建了一个与 ObjectOutputStream 连接到相同文件的 ObjectInputStream,并且从 ObjectInputStream 中读入一个对象,并将其转换为 Person 对象,最后将读入 Person 对象的值打印到 控制台。

关闭 ObjectInputStream

当你完成从 ObjectInputStream 读取数据的操作后,务必牢记将其关闭。值得注意的是,关闭 ObjectInputStream 时,与之关联的用于读取数据的 InputStream 实例也会随之关闭。

若要关闭 ObjectInputStream,只需调用它的 close() 方法即可。如下:

objectInputStream.close();

您还可以使用 Java 7 中引入的 try-with-resources 结构,如下:

InputStream input = new FileInputStream("object.data");
try(ObjectInputStream objectInputStream = new ObjectInputStream(input)){
    Person personRead = (Person) objectInputStream.readObject();
    //...
}

注意,此处不再有任何显式的 close() 方法调用,因为 try-with-resources 结构已自动处理资源关闭问题。

另外,首个 FileInputStream 实例并非在 try-with-resources 代码块中创建,这意味着该代码块不会自动关闭此 FileInputStream 实例。不过,当 ObjectInputStream 关闭时,它会同步关闭其所读取的 InputStream 实例。所以,FileInputStream 实例会在 ObjectInputStream 关闭时一同被关闭。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号