MST
星途 面试题库

面试题:Java序列化中如何自定义序列化和反序列化过程

在Java序列化场景下,当默认的序列化机制无法满足需求时,需要自定义序列化和反序列化过程。请阐述如何通过重写哪些方法来自定义这个过程,并举例说明一个实际场景为何需要这么做。
17.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

重写方法

  1. writeObject 方法
    • 若要自定义序列化过程,需在类中重写 private void writeObject(java.io.ObjectOutputStream out) throws IOException 方法。在此方法中,可以精确控制对象的哪些字段需要被序列化以及如何序列化。例如,如果对象中有一些敏感信息(如密码字段),不希望直接使用默认序列化机制将其写入流中,就可以在 writeObject 方法中跳过该字段的序列化,或者对该字段进行特殊处理(如加密后再序列化)。
  2. readObject 方法
    • 为了匹配自定义的序列化过程,还需要重写 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException 方法。这个方法用于从输入流中读取数据并重构对象。它要与 writeObject 方法的逻辑相对应,按照 writeObject 方法写入数据的顺序和方式来读取数据,以正确地恢复对象状态。

实际场景举例

假设我们有一个 User 类,包含用户名(username)、密码(password)和年龄(age)字段。在序列化时,我们不希望密码以明文形式存储在序列化文件中。

import java.io.*;

public class User implements Serializable {
    private String username;
    private transient String password; // transient 关键字表示该字段不参与默认序列化
    private int age;

    public User(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

    // 自定义序列化方法
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.writeObject(username);
        // 对密码进行加密后再写入(这里简单示例为转换为大写)
        out.writeObject(password.toUpperCase()); 
        out.writeInt(age);
    }

    // 自定义反序列化方法
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        username = (String) in.readObject();
        // 读取加密后的密码并处理(这里简单示例为转换回小写)
        password = ((String) in.readObject()).toLowerCase(); 
        age = in.readInt();
    }
}

在这个场景中,通过自定义序列化和反序列化过程,我们确保了敏感信息(密码)在序列化文件中不以明文形式存在,提高了数据的安全性。