Java オブジェクトのシリアライズについて

Java オブジェクトのシリアライズについて

このページでは、Javaでのオブジェクトのシリアライズについて詳しく解説します。基本的な概念から具体的な例、注意点までを取り上げます。

シリアライズとは

シリアライズとは、オブジェクトの状態をバイトストリームに変換するプロセスです。これにより、オブジェクトをファイルに保存したり、ネットワークを介して送信したりすることが可能になります。

シリアライズの用途

シリアライズは以下の用途で使用されます。

  • オブジェクトを永続化(ファイルやデータベースに保存)する。
  • リモートプロシージャコール(RMI)でオブジェクトを転送する。
  • キャッシュやセッションのデータ保存に使用する。

Javaにおけるシリアライズ

Javaでは、java.io.Serializableインターフェースを実装することでシリアライズ可能なオブジェクトを作成できます。このインターフェースにはメソッドが含まれていません。マーカーインターフェースとして動作し、オブジェクトがシリアライズ可能であることを示します。

基本的なシリアライズの例

以下は、オブジェクトをファイルにシリアライズし、後でデシリアライズする基本的な例です。


import java.io.*;

// シリアライズ可能なクラス
class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    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 SerializationExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        // シリアライズ
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
            oos.writeObject(person);
            System.out.println("Person object serialized.");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // デシリアライズ
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person deserializedPerson = (Person) ois.readObject();
            System.out.println("Deserialized Person: " + deserializedPerson);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
    

transientキーワードの例

transientキーワードを使用すると、特定のフィールドをシリアライズ対象から除外できます。


import java.io.*;

class SensitiveData implements Serializable {
    private static final long serialVersionUID = 1L;
    private String username;
    private transient String password; // シリアライズされない

    public SensitiveData(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
        return "SensitiveData{username='" + username + "', password='" + password + "'}";
    }
}

public class TransientExample {
    public static void main(String[] args) {
        SensitiveData data = new SensitiveData("user1", "secret");

        // シリアライズ
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"))) {
            oos.writeObject(data);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // デシリアライズ
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"))) {
            SensitiveData deserializedData = (SensitiveData) ois.readObject();
            System.out.println("Deserialized Data: " + deserializedData);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
    

カスタムシリアライズの例

writeObjectおよびreadObjectメソッドをオーバーライドしてカスタムシリアライズを行うことができます。


import java.io.*;

class CustomData implements Serializable {
    private static final long serialVersionUID = 1L;
    private String data;
    private transient int length;

    public CustomData(String data) {
        this.data = data;
        this.length = data.length();
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
        oos.writeInt(length);
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        this.length = ois.readInt();
    }

    @Override
    public String toString() {
        return "CustomData{data='" + data + "', length=" + length + "}";
    }
}

public class CustomSerializationExample {
    public static void main(String[] args) {
        CustomData customData = new CustomData("Hello World");

        // シリアライズ
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("customData.ser"))) {
            oos.writeObject(customData);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // デシリアライズ
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("customData.ser"))) {
            CustomData deserializedCustomData = (CustomData) ois.readObject();
            System.out.println("Deserialized Custom Data: " + deserializedCustomData);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
    

デシリアライズ

デシリアライズは、シリアライズされたバイトストリームをオブジェクトに復元するプロセスです。ObjectInputStreamを使用して実行されます。

注意点とベストプラクティス

  • シリアライズ対象のクラスにはserialVersionUIDを定義することが推奨されます。
  • データのセキュリティを確保するため、暗号化を検討してください。
  • シリアライズされたデータの互換性を保つため、クラスの設計には注意が必要です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です