ZetCode

Java ObjectOutput 接口

最后修改时间:2025 年 4 月 16 日

java.io.ObjectOutput 接口扩展了 DataOutput,并提供了用于写入对象和基本数据类型的方法。它主要用于 Java 中的对象序列化。实现此接口的类可以将对象写入流。

ObjectOutputObjectOutputStream 和其他需要序列化对象的类实现。它结合了 DataOutput 的功能和对象写入能力。此接口对于 Java 的序列化机制至关重要。

ObjectOutput 接口概述

ObjectOutput 提供了用于写入基本类型和对象的方法。关键方法包括用于序列化对象的 writeObject 和用于基本类型的各种写入方法。该接口还包括刷新和关闭操作。

public interface ObjectOutput extends DataOutput, AutoCloseable {
    void writeObject(Object obj) throws IOException;
    void write(int b) throws IOException;
    void write(byte[] b) throws IOException;
    void write(byte[] b, int off, int len) throws IOException;
    void flush() throws IOException;
    void close() throws IOException;
    // DataOutput methods...
}

上面的代码显示了 ObjectOutput 提供的关键方法。这些方法允许将对象和基本数据类型写入输出流。该接口扩展了 DataOutputAutoCloseable

将对象写入文件

此示例演示了使用 ObjectOutput 进行基本对象序列化。我们创建一个简单的类,实现 Serializable,并将一个实例写入文件。 ObjectOutputStream 实现了 ObjectOutput

Main.java
import java.io.*;

class Person implements Serializable {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        try (ObjectOutput out = new ObjectOutputStream(
                new FileOutputStream("person.dat"))) {
            
            Person person = new Person("John Doe", 30);
            out.writeObject(person);
            System.out.println("Person object written to file");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例创建一个实现 SerializablePerson 类。然后,我们创建一个实例并使用 ObjectOutput 将其写入文件。 try-with-resources 确保了流的正确关闭。序列化数据以二进制格式写入。

写入基本数据类型

ObjectOutputDataOutput 继承了基本类型写入方法。此示例演示了如何将各种基本类型写入文件。这些方法与 DataOutputStream 中的方法类似。

Main.java
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try (ObjectOutput out = new ObjectOutputStream(
                new FileOutputStream("primitives.dat"))) {
            
            out.writeBoolean(true);
            out.writeByte(65); // 'A'
            out.writeChar('B');
            out.writeDouble(3.14159);
            out.writeFloat(2.718f);
            out.writeInt(42);
            out.writeLong(123456789L);
            out.writeShort(32767);
            
            System.out.println("Primitives written to file");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例使用 ObjectOutput 方法将各种基本类型写入文件。每个方法都以二进制格式写入其特定类型。可以使用 ObjectInput 中相应的方法将数据读回。写入顺序必须与读取顺序匹配。

写入字节数组

ObjectOutput 提供了用于写入字节数组的方法。这些方法对于写入原始二进制数据很有用。这些方法可以写入整个数组或数组的一部分。这提供了数据输出的灵活性。

Main.java
import java.io.*;

public class Main {
    public static void main(String[] args) {
        byte[] data = {0x48, 0x65, 0x6C, 0x6C, 0x6F}; // "Hello" in ASCII
        
        try (ObjectOutput out = new ObjectOutputStream(
                new FileOutputStream("bytes.dat"))) {
            
            // Write entire array
            out.write(data);
            
            // Write portion of array
            out.write(data, 1, 3); // Writes 'ell'
            
            System.out.println("Byte arrays written to file");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了使用 ObjectOutput 写入字节数组。首先,我们写入整个数组,然后写入数组的一部分。第二次写入使用偏移量和长度来指定要写入的字节。这对于分块处理大型数组很有用。

组合对象和基本类型

此示例展示了如何在单个流中混合对象和基本类型的写入。读取时必须保留写入顺序。此技术在复杂的序列化场景中很常见。

Main.java
import java.io.*;

class Product implements Serializable {
    private String name;
    private double price;
    
    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
    
    @Override
    public String toString() {
        return "Product{name='" + name + "', price=" + price + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        try (ObjectOutput out = new ObjectOutputStream(
                new FileOutputStream("combined.dat"))) {
            
            // Write primitive header
            out.writeUTF("PRODUCT_DATA");
            out.writeInt(1); // Version
            
            // Write object
            Product product = new Product("Laptop", 999.99);
            out.writeObject(product);
            
            // Write more primitives
            out.writeLong(System.currentTimeMillis());
            out.writeBoolean(true);
            
            System.out.println("Combined data written to file");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例写入一个字符串头、版本号、产品对象、时间戳和布尔标志。 writeUTF 方法以修改后的 UTF-8 格式写入字符串。读取时,必须按照写入的相同顺序读取数据。

刷新和关闭流

ObjectOutput 提供了 flushclose 方法。刷新确保将所有缓冲数据写入底层流。关闭会释放资源,并且应该在完成后始终执行。

Main.java
import java.io.*;

public class Main {
    public static void main(String[] args) {
        ObjectOutput out = null;
        try {
            out = new ObjectOutputStream(
                new FileOutputStream("flush_close.dat"));
            
            out.writeUTF("Important data");
            
            // Ensure data is written immediately
            out.flush();
            System.out.println("Data flushed to file");
            
            // Write more data
            out.writeInt(42);
            
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                    System.out.println("Stream closed");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

此示例演示了使用显式刷新和关闭操作进行手动流管理。 flush 确保立即写入数据,这对于关键操作很重要。 finally 块保证即使发生异常,流也会关闭。

来源

Java ObjectOutput 接口文档

在本文中,我们涵盖了 Java ObjectOutput 接口的基本方法和特性。理解这些概念对于在 Java 应用程序中使用对象序列化至关重要。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员,在这个领域拥有多年的经验。我从 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程