のclone
操作ArrayList
はオブジェクトの浅いコピーを返すため、目的には適していません。手動での回避策は次のとおりです。
- ソース リストと同じサイズのターゲット配列リストを作成する
- ソース リストを反復し、その各項目のクローンをターゲット リストに作成します。
明らかに、これは配列リストに を実装するアイテムが含まれている場合にのみ機能clone
し、さらに、アイテムclone
操作が実際にディープ コピーを返す場合にのみ機能します。つまり、保証されていません。実際には、Java オブジェクトのディープ クローン機能を実装するのはまったく簡単ではありません。使用可能なオプションの感触をつかむために、 Java: インスタンスおよびその他の SO スレッドのディープ クローン作成/コピーに推奨されるソリューションに関する広範な議論を参照してください。そこで提供される回答に加えて、いくつかのオプションがあります。
シリアル化
階層内のすべての (必要な) オブジェクトをシリアル化できる場合は、次の単純なコードを使用してディープ クローンを作成できます。
public MyGraph deepCopy() {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
final ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
oos.close();
final ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray()));
final MyGraph clone = (QuicksortTest) ois.readObject();
return clone;
} catch (final Exception e) {
throw new RuntimeException("Cloning failed");
}
}
一部のディープ クローン ライブラリは、オブジェクト階層全体を完全にシリアライズ可能にするために、標準の Java シリアライゼーションをリフレクション ハックやバイト コード インストルメンテーションと組み合わせていることに注意してください。あなたはそれを必要とするかもしれませんし、必要としないかもしれません。
コピーツール
たとえば、Dozerは、高速なディープ コピー機能を提供します。Orikaも同じことを実現できますが、より多くの構成が必要になります。
public MyGraph deepCopy() {
final DozerBeanMapper mapper = new DozerBeanMapper();
final QuicksortTest clone = mapper.map(this, MyGraph.class);
return clone;
}
もちろん、唯一の欠点は、プロジェクトにプルする必要がある追加の依存関係です。
全接線では、deepCopy
メソッドは静的であってはなりません。また、オブジェクトをプライベートにしてゲッター/セッターを実装することで、オブジェクトの状態をカプセル化することを真剣に検討する必要があります。