EeBlog(テクニカルブログ)

第30回 直列化

今回のテーマは「直列化」です。

まずは「直列化とは何ぞや」というところから始めましょう。 直列化(serialize)とは、オブジェクトとそのインスタンス変数をバイト列やXMLに変換することです。 これにより、オブジェクトをファイルとして保存したり、ネットワークで送信することができるようになります。 直列化されたオブジェクトを復元する処理は直列化復元(deserialize)といいます。

直列化を利用するには、直列化したいクラスにjava.io.Serializableインターフェースをインプリメントします。 参照型のインスタンス変数がある場合は、その参照型にもSerializableインターフェースをインプリメントしなければいけません。

それではサンプルで確認していきましょう。 今回はSportsインターフェースにSerializableインターフェースを継承させました。

import java.io.Serializable;
public interface Sports extends Serializable { 
    void play(); }

@SuppressWarnings("serial") public class Badminton implements Sports { 
    @Override 
    public void play() { 
        System.out.println("バドミントンして遊びます。"); 
    } 
}

PlayerクラスにもSerializableインターフェースをインプリメントしています。

import java.io.Serializable;

@SuppressWarnings("serial") 
public class Player implements Serializable { 
    private Sports sports;

    public Player(Sports sports) { 
        this.sports = sports; 
        System.out.println("コンストラクタです。");     }

    public Sports getSports() { 
        return sports; 
    }
    public void play() { 
        System.out.println("ウォームアップします。");

        sports.play();

        System.out.println("クールダウンします。"); 
    } 
}

今回、Mainクラスでは直列化を利用したディープコピーを行っています。
まずオブジェクトを直列化し、それを直列化復元により新たなオブジェクトとして取得しているのです。

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable;

public class Main { 
    public static void main(String[] args) throws Exception { 
        Player player = new Player(new Badminton()); 
        player.play(); 
        System.out.println();

        Player clonePlayer = deepCopy(player); 
        clonePlayer.play(); 
        System.out.println();

        System.out.print("Playerのインスタンスが同じ:"); 
        System.out.println(player == clonePlayer); 
        System.out.print("Badmintonのインスタンスが同じ:"); 
        System.out.println(player.getSports() == clonePlayer.getSports()); 
    }

    @SuppressWarnings("unchecked") 
    public static <T extends Serializable> T deepCopy(T t) throws Exception { 
        if (t == null) { 
            return null; 
        }

    ByteArrayOutputStream byteOut = null; 
        ObjectOutputStream objectOut = null; 
        try { 
            byteOut = new ByteArrayOutputStream(); 
            objectOut = new ObjectOutputStream(byteOut); 
            objectOut.writeObject(t); 
        } finally { 
            objectOut.close(); 
        }

        ObjectInputStream objectin = null; 
        T copy = null; 
        try { 
            objectin = new ObjectInputStream(new ByteArrayInputStream
                                                  (byteOut.toByteArray())); 
            copy = (T) objectin.readObject(); 
        } finally { 
            objectin.close(); 
        } 
        return copy; 
    } 
}

前回のシャローコピーの場合とは違い、PlayerクラスのフィールドのSportsのインスタンスも異なるという結果が出ます。