Webサイト制作コースのお申し込みはこちら Webサイト制作コースのお申し込みはこちら

Javaでは Serializable インターフェイスを実装したクラスは、シリアライズ(日本語では直列化と呼ぶ)という操作で、メモリ上の Java のオブジェクトをハードディスクなどの記憶媒体に永続的に保存することができます。

この記事では、Serializable インターフェイスを実装したクラスを、シリアライズして保存する方法と、保存したオブジェクトを読み込み、再度メモリ上に復元するデシリアライズの方法を解説します。

シリアライズ(Serializable)

Java のオブジェクトをシリアライズ(Serializable)して、ディスク上に保存する方法から見ていきましょう。

Java のオブジェクトをシリアライズするには、対象のオブジェクトが java.io.Serializable インターフェイスを実装している必要があります。

今回は氏名、年齢の2つのプロパティを持った Person クラスを作成してシリアライズします。java.io.Serializable インターフェイスを忘れずに実装しておきましょう。

ポテパンダの一言メモ

java.io.Serializable インターフェイスは、メソッドがないマーカーインターフェイスであるため、このインターフェイスを実装してもオーバライドするメソッドなどはありません。

また、java.io.Serializableを実装していないクラスをシリアライズしようとすると、NotSerializableException が発生します。

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;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

シリアライズ対象のクラスの準備ができたら、 ObjectOutputStream を使って Java オブジェクトを出力ストリームに書き出す処理を書いていきます。

このオブジェクトを出力ストリームに書き出す行為をシリアライズ(日本語では直列化)と呼びます。

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.data"))) {
            Person person = new Person("山田太郎", 20);
            oos.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

デシリアライズ

シリアライズ(Serializable)で出力したオブジェクトを、復元して再度メモリ上に展開するにはデシリアライズを行います。

では、先程シリアライズで出力した Person クラスのファイルを、ObjectInputStream に読み込んでデシリアライズしてみましょう。

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) {

       // デシリアライズ
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.data"))) {
            Person person = (Person) ois.readObject();
            System.out.println("name=" + person.getName());
            System.out.println("age=" + String.valueOf(person.getAge()));
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

■ 実行結果

name=山田太郎
age=20

このように、シリアライズによってファイルに保存した Java オブジェクトが、デシリアライズによって復元されています。

シリアライズについてもっと知る

Java でシリアライズ・デシリアライズをする基本的な方法を解説してきました。

ここからは、シリアライズに関するもう少し詳しい内容を確認していきましょう。

serialVersionUIDを付けよう

「serialVersionUID」とはクラスのバージョンのようなもので、java.io.Serializable インターフェイスを実装したシリアライズ可能なクラスに static 変数として次のように定義することが推奨されています。

import java.io.Serializable;

public class Person implements Serializable {

  private static final long serialVersionUID = 1L;

  ・・・
}

この「serialVersionUID」は、クラスにプロパティを追加した時など、何かしら構造的な変更をした時にバージョンを上げいきます。

異なるserialVersionUIDのクラスはデシリアライズ不可

デシリアライズ時に「serialVersionUID」が異なるファイルを読み込もうとすると、java.io.InvalidClassException が発生します。

ポテパンダの一言メモ

このように「serialVersionUID」をクラスに宣言することにより、異なるバージョンのクラスを読み込んでしまうことで発生しうる不正な動作を防ぐことができます。

「serialVersionUID」は必要?

「serialVersionUID」が定義されていないクラスでも、コンパイル時に警告は出るがシリアライズやデシリアライズをすることは可能です。

公式の JavaDoc には「serialVersionUID」について次のように書かれています。

直列化可能クラスがserialVersionUIDを明示的に宣言しない場合、直列化ランタイムは「Java(TM)オブジェクト直列化仕様」で説明されているように、クラスのさまざまな側面に基づいて、クラスのserialVersionUIDのデフォルト値を計算します。ただし、すべての直列化可能クラスがserialVersionUID値を明示的に宣言することを強くお薦めします。
Serializable (Java Platform SE 8)

つまり、省略した場合は自動で付与するが、明示的に「serialVersionUID」を定義することを推奨すると書かれています。

「serialVersionUID」を極力変えない工夫を

前述したように「serialVersionUID」を変更すると、過去に作成したファイルをデシリアライズする時にエラーとなります。

もちろん、大幅にクラスの内容を変えた場合はバージョンを上げて、古いバージョンのファイルをデシリアライズした時にエラーにすることで、想定外の動作を防ぐ必要があります。

しかし、影響が少ないプロパティを1つ追加する程度の変更であれば「serialVersionUID」は変更せず、新しプロパティが null になった場合などても問題なく動作するような作りにし、より汎用的な設計にしておいた方がよいでしょう。

まとめ

Java のオブジェクトをファイルなどに保存するシリアライズ(Serializable)と、それを復元するデシリアライズ処理について解説してきました。

シリアライズをすることで、オブジェクトのインスタンスの内容を別のサーバーにファイルで送信したりできるなど、さまざまな用途で使えるため是非おぼえておきましょう。

【関連記事】
【Java】クラス?メソッド?クラスメソッドって何?

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。