Javaシリアライズの基本と実装方法

Javaでオブジェクトをシリアライズ可能にするためには以下の条件を満たす必要があります。

  1. Serializableインタフェースの実装
  2. スーパークラスがシリアライズ可能かデフォルトコンストラクタを持つ
  3. フィールドがシリアライズ可能かtransient修飾子付きであること
  4. オプションでprivate static final long serialVersionUIDの明示的定義

serialVersionUIDを明示的に定義しない場合、ランタイムで自動生成されます。明示定義の利点は、デシリアライズ時のバージョン一致確認により、不一致時に例外を投げてデータ破損を防ぐことです。

カスタムシリアライズ処理は以下のメソッドで実装可能です。

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    // ユーザー定義ロジック
}

private void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
    // ユーザー定義ロジック
}

サンプルコード:

import java.io.Serializable;
import java.io.*;

public class UserData implements Serializable {
    private String userName;
    private int userAge;
    private static final long serialVersionUID = 12345L;

    public UserData(String name, int age) {
        this.userName = name;
        this.userAge = age;
    }

    // ゲッター/セッター

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("読み込み: " + this);
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        System.out.println("書き込み: " + this);
    }

    @Override
    public String toString() {
        return String.format("名前=%s, 年齢=%d", userName, userAge);
    }
}
import java.nio.file.*;
import java.io.*;

public class DataWriter {
    public static void main(String[] args) {
        Path filePath = Paths.get(System.getProperty("user.dir")).resolve("data.bin");
        try {
            Files.deleteIfExists(filePath);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        try (ObjectOutputStream out = new ObjectOutputStream(
                new BufferedOutputStream(Files.newOutputStream(filePath, CREATE, WRITE)))) {
            
            UserData user1 = new UserData("田中", 30);
            out.writeObject(user1);
            out.reset(); // オブジェクトキャッシュのリセット
            user1.setUserName("佐藤");
            user1.setUserAge(25);
            out.writeObject(user1);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import java.nio.file.*;
import java.io.*;

public class DataReader {
    public static void main(String[] args) {
        Path filePath = Paths.get(System.getProperty("user.dir")).resolve("data.bin");
        try (ObjectInputStream in = new ObjectInputStream(
                new BufferedInputStream(Files.newInputStream(filePath, READ)))) {
            
            UserData userData = null;
            while (true) {
                userData = (UserData) in.readObject();
            }
        } catch (EOFException e) {
            System.out.println("ファイル終了: " + filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

タグ: Java シリアライズ Serializable IO操作 オブジェクトストリーム

7月30日 18:57 投稿