【HeadFirst系列之HeadFirstJava】第14天之对象的序列化与文件输入/输出

Scroll Down

从零开始学Java:对象的序列化与文件输入/输出

大家好!今天我们来聊聊Java中的一个非常实用的功能——对象的序列化与文件的输入/输出。如果你正在学习Java,或者已经对Java有了一定的了解,那么这一部分内容绝对是你不能错过的。通过序列化,我们可以将对象保存到文件中,并在需要的时候重新加载到内存中。这在很多实际应用中都非常有用,比如保存游戏进度、存储用户数据等。

本文的内容基于《Head First Java》第14章,我们将从核心概念出发,结合实际代码示例,帮助你快速掌握这一重要技能。

14-序列化和文件的输入输出-保存对象-前言

什么是序列化?

序列化(Serialization) 是将对象的状态转换为字节流的过程,以便将其保存到文件或通过网络传输。反序列化(Deserialization)则是将字节流重新转换为对象的过程。

简单来说,序列化就是将一个对象“冻结”成字节流,保存到文件中;反序列化则是将文件中的字节流“解冻”成原来的对象。


为什么要序列化?

  1. 持久化存储:将对象保存到文件中,即使程序关闭后,数据也不会丢失。
  2. 网络传输:将对象序列化后可以通过网络发送到其他计算机。
  3. 深拷贝:通过序列化和反序列化可以实现对象的深拷贝。

如何实现序列化?

在Java中,实现序列化非常简单,只需要让类实现 java.io.Serializable 接口即可。这个接口是一个标记接口,没有任何方法,只是用来告诉JVM这个类可以被序列化。

1. 实现 Serializable 接口

import java.io.Serializable;

public 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 + "}";
    }
}

2. 将对象序列化到文件

要将对象保存到文件中,我们需要使用 ObjectOutputStream。以下是一个简单的示例:

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

public class SerializeExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 25);

        try (FileOutputStream fileOut = new FileOutputStream("person.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            // 将对象写入文件
            out.writeObject(person);
            System.out.println("对象已序列化并保存到 person.ser 文件中");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行这段代码后,当前目录下会生成一个 person.ser 文件,里面保存了 Person 对象的数据。


3. 从文件中反序列化对象

要从文件中恢复对象,我们需要使用 ObjectInputStream。以下是一个示例:

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserializeExample {
    public static void main(String[] args) {
        try (FileInputStream fileIn = new FileInputStream("person.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            // 从文件中读取对象
            Person person = (Person) in.readObject();
            System.out.println("从文件中反序列化的对象: " + person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行这段代码后,控制台会输出反序列化后的 Person 对象信息。


序列化的注意事项

  1. transient 关键字
    如果某个字段不需要被序列化(比如密码),可以使用 transient 关键字标记它。序列化时,transient 字段会被忽略。

    private transient String password; // 不会被序列化
    
  2. 版本控制
    每个序列化的类都有一个唯一的 serialVersionUID,用于标识类的版本。如果类的结构发生变化(比如增加字段),反序列化时可能会抛出 InvalidClassException。为了避免这个问题,可以显式声明 serialVersionUID

    private static final long serialVersionUID = 1L;
    
  3. 序列化的限制

    • 静态字段不会被序列化。
    • 不是所有的对象都可以序列化,只有实现了 Serializable 接口的对象才能被序列化。

文件的输入/输出

除了序列化,Java还提供了多种文件读写的方式。比如使用 FileWriterFileReader 来处理文本文件,或者使用 BufferedReaderBufferedWriter 来提高读写效率。

示例:使用 BufferedWriter 写入文件

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriteExample {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
            writer.write("Hello, World!");
            writer.newLine();
            writer.write("This is a text file.");
            System.out.println("数据已写入文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

示例:使用 BufferedReader 读取文件

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class FileReadExample {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("output.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

通过本文,我们学习了Java中对象的序列化与反序列化,以及文件的输入/输出操作。序列化是一个非常强大的功能,可以帮助我们轻松实现对象的持久化存储和网络传输。而文件的输入/输出则是处理文本数据的常用方式。

如果你对这部分内容感兴趣,不妨动手试试,写一个简单的程序来保存和加载对象吧!希望这篇文章能帮助你更好地理解Java的序列化与文件操作。


关注我,获取更多Java学习资源和编程技巧!