61

java.util.Calendar.clone()は、「...同じプロパティを持つ新しいカレンダー」を返し、「このカレンダーの浅いコピー」を返します。

ここでSOで回答されているように、これは浅いコピーではないようです。その質問は言語に依存しないというタグが付けられており、 Javaは言語に依存しない定義に従っていないようです。コードをステップスルーすると、言語に依存しない構造だけでなく、構造と要素がこの新しいオブジェクトにコピーされていることに気付きます。

Javaでは、浅いコピーとは何ですか?

Javaディープコピー(存在する場合)とどのように異なりますか?

4

11 に答える 11

91

浅いコピーは、クラス内の参照の値をコピーするだけです。ディープコピーは値をコピーします。与えられた:

class Foo {
  private Bar myBar;
  ...
  public Foo shallowCopy() {
    Foo newFoo = new Foo();
    newFoo.myBar = myBar;
    return newFoo;
  }

  public Foo deepCopy() {
    Foo newFoo = new Foo();
    newFoo.myBar = myBar.clone(); //or new Bar(myBar) or myBar.deepCopy or ...
    return newFoo;
  }
}

Foo myFoo = new Foo();  
Foo sFoo = myFoo.shallowCopy();  
Foo dFoo = myFoo.deepCopy();  

myFoo.myBar == sFoo.myBar => true  
myFoo.myBar.equals(sFoo.myBar) => true  
myFoo.myBar == dFoo.myBar => **false**  
myFoo.myBar.equals(dFoo.myBar) => true  

この場合、浅いコピーには同じ参照(==)があり、深いコピーには同等の参照(.equals())しかありません。

浅くコピーされた参照の値に変更が加えられた場合、同じ参照を共有しているため、コピーはその変更を反映します。深くコピーされた参照の値に変更が加えられた場合、同じ参照を共有しないため、コピーはその変更を反映しません。

C-ism

int a = 10; //init
int& b = a; //shallow - copies REFERENCE
int c = a;  //deep - copies VALUE
++a;

結果:

a is 11  
*b is 11  
c is 10
于 2009-07-24T03:50:18.027 に答える
17

浅いコピーは、同じメモリ位置へのポインタのセットにすぎません。実際には実際のコピーは作成されないため、メモリ使用量は少なくなります。

ディープコピーの場合、メモリセグメントの正確なコピーが作成され、ポインタが新しいメモリ位置に設定されます。したがって、理論的には、この場合、メモリ消費量は2倍になるはずです。

于 2009-07-24T03:38:30.593 に答える
9

浅いコピーはオブジェクトへの参照ポインタのコピーであり、深いコピーはオブジェクト自体のコピーです。Javaでは、オブジェクトはバックグラウンドで保持されます。オブジェクトを処理するときに通常操作するのはポインターです。変数名は、オブジェクトのメモリ空間を指します。次のように、ある変数を別の変数と等しく設定すると、浅いコピーが作成されます。

Object B = A;

オブジェクトAのプロパティを取得し、それらを新しいオブジェクトBに配置することで、ディープコピーを作成できます。

Object B = new Object(A.getProperty1(), A.getProperty2()...);

これは、浅いコピーを作成してタスクを実行すると、オブジェクトのすべての浅いコピーに影響するという点で、プログラムの動作に影響します。ディープコピーに変更を加えると、そのコピーのみが影響を受けます。これがあなたにとって十分に詳細であることを願っています。

于 2009-07-24T03:43:14.437 に答える
3

1.6ドキュメントドキュメントCalendar.cloneには、「このオブジェクトのコピーを作成して返す」と記載されています。で指定されている文字通りの浅いコピーはObject.clone意味がありません。Javaは、かなり典型的な意味で「浅いコピー」という用語を使用します。

于 2009-07-24T03:38:01.060 に答える
2

ドキュメントに誤りがあるようです。AndroidのCalendar.cloneメソッドが、「浅いコピー」の一般的な定義(Javaまたはその他)にどのように適合するかわかりません。

于 2009-07-24T05:10:29.533 に答える
2

SHALLOWCOPYはPASS-BY-REFERENCEです...DEEPCOPYはPASS-BY-VALUEです…コンテキストは異なりますが、プロセスはまったく同じです。まず、Javaメソッド呼び出しでは、プリミティブは値で渡され、オブジェクトは参照で渡されることを覚えておいてください(他の言語では、オブジェクトも値で渡される場合があります)。現在、Javaでは、呼び出し元が呼び出されたメソッドにプリミティブを渡すと、呼び出されたメソッドはそれを新しいローカル変数として複製します。これはディープコピーです。一方、オブジェクトが渡された場合、呼び出されたメソッドは同じオブジェクトへの新しいローカル参照のみを作成します。これはシャローコピーです。呼び出しを理解している場合は、深い/浅いコピーを理解し、その逆も同様です。

于 2019-10-13T02:19:10.183 に答える
1

このドキュメントはどこで入手できますか?

java.sun.comの公式Java6ドキュメントでは、Calendar.clone()がオブジェクトのコピーを返すだけです。浅いという言及はありません。

より一般的には、Javaのシャローコピーは、新しいオブジェクト参照を取得するが、新しいオブジェクトは元のデータへの参照を(直接的または間接的に)保持するものです。

例えば:

class MyClass{
  private List<Integer> innerList;

  public MyClass(List<Integer> list) { innerList = list; }

  //Some code...

  public Object clone(){
    return new MyClass(innerList);
  }
}

clone()でシャローコピーを返します。

于 2009-07-24T03:38:04.960 に答える
1

まず、1次元配列について話している場合、ArrayListのJavadocは、配列のcopyOfメソッドを使用しているため、多少間違っています。したがって、clone()は、少なくとも1.5以降(これ以上テストしませんでした)、1次元のコピーを返します。これがJavaでの「浅い」の意味です。1次元

詳細については、http : //www.javapractices.com/topic/TopicAction.do?Id=3を参照してください。したがって、clone()は浅いコピーではありません!1次元配列の実際の浅いコピーが必要な場合は、それを参照してください。

Array a = new Array();
Array b = a;                    //a is only a shallow copy, nice for synchronisation

Javaは値渡しを行うため、Javaの配列には注意が必要ですが、配列の値はポインターにすぎません。一方、これによりオブジェクトを同期できるようになります。これは素晴らしいことです。それでも、配列(またはArrayLists)内で配列を使用する場合は、コンテナ配列(またはArrayList)のclone()が値をコピーせず、参照のみをコピーするため、いくつかの問題があります。したがって、配列を配列に配置するのではなく、配列内のオブジェクトのみを処理する必要があります。

また、Javadocは理解しにくい場合があるため、テストを試してみてください...

楽しむ!

于 2012-10-20T07:38:39.687 に答える
1

浅いコピーは、オブジェクト参照をターゲット参照にコピーするだけです。ヒープ上に新しいオブジェクトは作成されません。デフォルトでは、Javaはclone()関数を使用してシャロークローンを作成します。

ヒープ上に新しいオブジェクトを取得するには、シリアル化と逆シリアル化によって実装できるディープクローンを実行する必要があります。

于 2017-04-05T14:02:22.783 に答える
0

浅いコピーでは、クローンオブジェクトにはプリミティブ値のコピーがありますが、オブジェクト参照は元のコピーと同じオブジェクトを参照します。浅いコピーには重大な欠点があり、複製されたオブジェクトと元のコピーは同じアドレスオブジェクトを参照します。複製されたオブジェクトがアドレスオブジェクトに加えた変更は、元のコピーにも反映されます。これは望ましくない動作です。私たちが本当に望んでいたのは、ユーザーオブジェクトの2つの別々のコピーです。このような状況では、ディープコピーが役に立ちます。

ディープコピーは、プリミティブ値だけでなく、オブジェクト参照のコピーも作成します。

あなたはここでこれに関する実際の例を見ることができます:https ://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/

于 2017-11-09T09:42:30.773 に答える
0

浅いコピー:このクローン作成では、クローン作成されたオブジェクトへの変更は元のオブジェクトにも反映されます。

ディープコピー:このクローン作成では、個別のクローン作成メモリが割り当てられます。つまり、クローン作成されたオブジェクトへの変更は元のオブジェクトに反映されません。

于 2019-07-16T04:23:33.997 に答える