5

MyGraph のオブジェクトを複製しようとしていますが、それをディープ コピーにしたいので、オブジェクト内の配列リストも複製されます。今私は持っています:

public static MyGraph deepCopy(MyGraph G){
    MyGraph Copy = (MyGraph) G.clone();

    Copy.VertexG = (ArrayList<Integer>) G.VertexG.clone();
    Copy.EdgeG = (ArrayList<String>) G.EdgeG.clone();

    return Copy;
}

arraylist のクローンを作成しようとすると、エラーが返されます。これが配列リストをオブジェクトに追加する正しい方法かどうかはわかりません。

4

4 に答える 4

3

clone操作ArrayListはオブジェクトの浅いコピーを返すため、目的には適していません。手動での回避策は次のとおりです。

  1. ソース リストと同じサイズのターゲット配列リストを作成する
  2. ソース リストを反復し、その各項目のクローンをターゲット リストに作成します。

明らかに、これは配列リストに を実装するアイテムが含まれている場合にのみ機能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メソッドは静的であってはなりません。また、オブジェクトをプライベートにしてゲッター/セッターを実装することで、オブジェクトの状態をカプセル化することを真剣に検討する必要があります。

于 2013-03-01T10:38:09.567 に答える
0

呼び出すすべてのクラスは、インターフェイスclone()を実装する必要がありCloneableます。あなたのコメントから、私はあなたのMyGraphクラスがインターフェースを実装していないことを理解していCloneableます. その場合、Object.clone()をスローしCloneNotSupportedExceptionます。

于 2013-03-01T10:58:20.143 に答える
0

すべてのクラスがCloneableインターフェイスを実装し、それらにclone()定義cloningがあることを確認する必要があるため、ディープコピーを実行しようとするのは複雑です。

より良い方法は、を介して行うことCopy Constructor or Serializationです。詳しく書いたブログはこちらです。それが役に立てば幸い :)

于 2013-03-01T11:05:20.033 に答える
0

Java でのクローン作成に関する基本的な概念上の問題 [おそらく基本的な問題] はタイプのフィールドがList<String>少なくとも 5 つの非常に異なるものを表すことができるということです。

  • 変更可能なリストへの唯一の現存する参照。変更可能な状態をカプセル化するために使用されますが、唯一の現存する参照であり、その ID をカプセル化することはできません (リストは、同じアイテムを保持する別のリストに置き換えることができます。プログラムのセマンティクスを変更することなく)。このフィールドを含むオブジェクトの正しいクローンは、同じ項目を保持する別のリストへの参照を保持します。

  • 変更可能なリストへの参照。それ自体は変更可能ですが、実際にそれを変更するものには公開されません。この参照は、他のコードがリストを変更したり、そうする可能性のあるコードに公開したりすることを控える場合にのみ、他のコードと共有できます。このフィールドを含むオブジェクトの正しいクローンは、元のリストまたは同じ項目を保持する別のリストへの参照を保持できます。

  • 不変リストへの参照。この参照は、そのコードがそれを公開する方法に関係なく、他のコードと自由に共有できます。上記のように、このフィールドを含むオブジェクトの正しいクローンは、元のリストまたはコピーへの参照を保持できます。

  • リストにカプセル化された他のオブジェクトの状態の側面にこれをバインドする目的で保持される、他のオブジェクトが所有する変更可能なリストへの参照。フィールドを保持するオブジェクトの正しいクローンは、そのコピーではなく、同じ listへの参照を保持する必要があります。

  • このオブジェクトが所有しているが、このオブジェクトの状態を監視するか、このオブジェクトに情報を供給する目的で他のオブジェクトも参照している可変リストへの参照。このフィールドを保持するオブジェクトを単独で正しく複製することはできませんが、相互接続されたオブジェクトのグループを複製して、新しいオブジェクトのセットに元のグループのオブジェクトと同型の相互接続のセットを与えることは可能かもしれません。

フィールドが参照を保持するオブジェクトの具象型は、上記のケースのいくつかを区別する場合がありますが、それらすべてを区別することはできません。特に、最初と 4 番目のシナリオでは、どちらのシナリオでも参照がArrayList<string>.

于 2013-03-06T17:05:59.433 に答える