2013-02-28 5 views
9

最終的なクラスはNameAndValueです。 NameAndValueオブジェクトの配列をSystem.arrayCopy()でコピーしました。コピーした配列のオブジェクトをNameAndValueに変更すると、元の配列に反映されます。System.arrayCopy()はオブジェクトまたはオブジェクトへの参照をコピーしますか?

public final class NameAndValue 
{ 
    public String name; 
    public String value; 

    public NameAndValue() 
    { 

    } 

    public NameAndValue(String name,String value) 
    { 
     this.name = name; 
     this.value = value; 
    } 
} 

public class Main 
{ 
    public static void main(String[] args) 
    { 
     NameAndValue[] nv = new NameAndValue[4]; 
     nv[0] = new NameAndValue("A", "1"); 
     nv[1] = new NameAndValue("B", "2"); 
     nv[2] = new NameAndValue("C", "3"); 
     nv[3] = new NameAndValue("D", "4"); 

     NameAndValue[] nv2 = new NameAndValue[4]; 
     System.arraycopy(nv, 0, nv2, 0, 2); 
     nv2[2] = new NameAndValue("Y","25"); 
     nv2[3] = new NameAndValue("Z","26"); 

     for (int i = 0; i < 2; i++) 
     { 
      NameAndValue[] nv3 = new NameAndValue[4]; 
      System.arraycopy(nv2, 0, nv3, 0, 4); 
      nv3[2].value = String.valueOf(i); 
      nv3[3].value = String.valueOf(i+1); 

      System.out.println(nv2[2].value); 
      System.out.println(nv2[3].value); 
      System.out.println("-----------------------"); 
     } 
    } 
} 

私は、すべてのケースで25と26と右の出力を持っている必要があります

0 
1 
----------------------- 
1 
2 
----------------------- 

、と私は出力を取得しています?なぜそれが変わるのですか?

答えて

18

System.arrayCopy()は、オブジェクトまたはオブジェクトへの参照をオブジェクトにコピーしますか?

リファレンス、それは浅いコピーです。驚いたことに、the docs don't say that explicitlyは暗黙のうちにのみは配列要素をコピーすることについて話し、それらが参照するものは再帰的にコピーしません。

それはあなたがこれを持っていたかのようにまったく同じです:

NameAndValue nv1 = new NameAndValue("A", "1"); 
NameAndValue nv2 = nv1; 
nv2.value = "4"; 
System.out.println(nv1.value); // 4 

各配列要素は、上記nv1nv2 VARSのようなものです。 nv1nv2が同じ基礎となるオブジェクトを参照する(ポイントする)ので、配列エントリも同じ配列から別の配列にコピーされるときも含めて配列エントリを参照します。

+1

私は(コアのJava APIと様々な人気のある図書館で)多くのことを発見しましたそれは浅いコピーはドキュメントで明示的にこれを明示的に述べていません。 – berry120

+0

@ berry120:そうです。それは合理的な仮定です。私はそれを明示的にしましたが、私が推測するように簡潔にする価値があります。:-) –

+0

ああ、同意しました:-) – berry120

2

どちらの配列も同じ基本オブジェクトを参照しているため、変更されます。新しいオブジェクトを配列内の位置に割り当てることができ、それは他の配列には反映されませんが、両方の配列が指し示すオブジェクトを変更すると、その両方が異なって見えます。

この意味では、厳密には参照渡しではなく、「値による参照」を渡しますが、参照が同じままであるため、表示される効果があります。

特に明記しない限り、このようなコピーはほとんどの場合、Javaのシャローコピーです。これは例外ではありません。

1

私が知る限り、arraycopyは浅いコピーです。つまり、新しい配列は古い配列の要素のアドレスを参照します。したがって、いずれかの値を調整すると、両方に反映されます

1

System.arraycopyは浅いコピーです。理由は次のとおりです。

メモリ内のポインタをコピーするだけのmemcpy()などのJNIを使​​用しています。非常に高速な操作です。出力はこのようなものです

0
int[] a = {1, 2, 3}; 
    int[] b = new int[3]; 
    System.arraycopy(a, 0, b, 0, 3); 
    b[1] = 0; 
    System.out.println(Arrays.toString(b)); 
    System.out.println(Arrays.toString(a)); 

: [1、0、3] [1、2、3]

+0

これは、それが浅いコピーを行うことを示しています。あなたの構造は深さがありません。深みがあった場合、 'System.arraycopy'は深いコピーをしないことがわかります。 –

+0

はい、そうです。配列要素の参照を変更しないでテストしましたが、代わりに参照するデータの内容を変更しました。私はこれらの2つの配列の値が同じであることを発見しました。すごい! –

関連する問題