Java シリアル化を利用して手軽にディープクローンを行う




Object#clone()でクローンできるよ?

Javaでは標準でクローンをサポートしていますので、簡単にクローンができます。
・・・が、Objectクラスにあるクローンメソッドは、シャローコピー(浅いコピー)によるクローンです。

ざっくり言うと、変数の箱は用意するけど、中身は共有することになります。
よって、クローン元のオブジェクトに操作を行うと、クローン先のオブジェクトにも反映される等、影響を受ける可能性があります。
その時点でのオブジェクトをバックアップしたりするには、不向きです。(・・というか、困ります)

これってクローンじゃないじゃん?

いいえ。立派なクローンです。

Javaのオブジェクトは、参照型というものでできます。
つまり、実体のデータを指し示す参照(≒ポインタ)をコピーしたことになります。

ちなみに、クローン羊を作るようにオブジェクトの実体をコピーすることを「ディープコピー」といいます。

じゃあ、実体をクローンしたいんだけど・・・?

はい、clone()メソッドをオーバーライドしたり、その他メソッドでひたすらに変数をコピーしてください。
しかも、上の参照コピーを考慮してやると良いです。

なんて言うと、怒られるので・・(-_-メ)
汎用サンプルを用意してみました。

サンプル

クローン対象のCloneTestクラスは、色から連想する果物をHashMapで格納しています。
これをクローンした後、クローン元を操作した際の結果を出力します。

実行結果

一目瞭然ですが、Object#clone()によるシャローコピーと、CloneTest#cloneDeep()によるディープコピーの挙動の差がわかります。

サンプルの解説

一度、シリアライズ化した後、オブジェクトを再構成することで、簡単にディープコピーができます。
ファイルにセーブして、ファイルからロードしたようなイメージです。

このサンプルは、シリアライズ化を利用することで汎用的にディープコピーできるようにしています。
よって、クローンしたいオブジェクトは、「Serializable」を実装する必要があります。
というわけで、ちょっと条件ありなので、常に使えるわけではないです。。