web-dev-qa-db-ja.com

clone():ArrayList.clone()私は浅いコピーをすると思った

_ArrayList<Integer> a=new ArrayList<Integer>();
a.add(5);
ArrayList<Integer> b=(ArrayList<Integer>)a.clone();
a.add(6);
System.out.println(b.toString());
_

上記のコードでは、clone()は浅いコピーを行うと思います。したがって、baは同じメモリ位置を指す必要があります。ただし、b.toString()を実行すると、答えは_5_のみになります。 clone()が浅いコピーを行う場合、なぜ_6_も表示されないのですか?

20

浅いコピーは、それらが同じメモリ位置を指すことを意味しません。それはただの割り当てです:_List b = a;_。

クローン作成により、newインスタンスが作成され、同じ要素が保持されます。つまり、2つの異なるリストがありますが、それらの内容は同じです。最初のリスト内のオブジェクトの状態を変更すると、2番目のリストで変更されます。 (不変のタイプ-Integerを使用しているため、これを観察することはできません)

ただし、clone()を使用しないことを検討する必要があります。コレクションでは正常に機能しますが、一般的には破損していると見なされます。コピーコンストラクターを使用する-new ArrayList(originalList)

50
Bozho

あなたが思ったようにだった場合cloneメソッドwouldその場合、以下の行と同等になるため、まったく役に立たない:

_ArrayList<Integer> b = (ArrayList<Integer>)a.clone();
ArrayList<Integer> b = a;
_

クローニングとは、実世界のシナリオのように、まったく同じプロパティを持つ2つのエンティティを作成するプロセスです(クローニング操作時)。

そして、Bozhoが述べたように-Java clone()]の概念を避けてください。

この質問とその答え は非常に価値があり、ジョシュ・ブロックス自身の作品に関するコメントへのリンクを提供します;-)

6
Andreas_D

これは実際に浅いコピーを行います。クローンのコメントはArrayListソースコードからです。

このArrayListインスタンスの浅いコピーを返します。 (要素自体はコピーされません。)

これを理解するために、ArrayListのcloneメソッドのスニペットを見てみましょう

v.elementData = Arrays.copyOf(elementData, size);

知っているように、オブジェクトを変数に割り当てると、Javaはそのオブジェクトの真新しいコピーを作成しません。代わりに、この変数は元のオブジェクトを指す別の参照になります。

したがって、elementDataはこのArrayListに入れられたオブジェクトへの参照を実際に格納しています。そして、クローンはこれらの参照をコピーするだけで、オブジェクトのレプリカは作成されません。

もちろん、複製されたArrayListへの新しい参照を削除または追加できます。

ただし、1つのArrayListで古いオブジェクトを変更すると、元のArrayListに影響します。 Integerは不変であるため、例を使用して説明するのは困難です。

副作用を見るために、カスタム可変オブジェクトを定義できます

class Person {
        private int a;

        public void setA(int a) {
            this.a = a;
        }
        public int getA() {
            return a;
        }
        @Override
        public String toString() {
            return String.valueOf(a);
        } 
   } 

その後、次のコードを使用してテストを行うことができます

        Person p1 = new Person();
        Person p2 = new Person();

        ArrayList<Person> tt = new ArrayList<Person>();
        tt.add(p1);
        tt.add(p2);

        ArrayList<Person> yy = (ArrayList<Person>) tt.clone();
        Person vv = yy.get(yy.indexOf(p2));
        vv.setA(12);
        yy.remove(p1);

        System.out.println("tt: " + tt);
        System.out.println("yy: " +yy);

出力は

tt:[0、12]
yy:[12]

副作用を参照してください:)? yyの要素のみを変更しますが、ttにも反映されます。

1
user2473519

浅いクローニングは、あなたが話しているObject.clone()によって提供されるデフォルトのクローニング戦略です。オブジェクトクラスのclone()メソッドは、新しいインスタンスを作成し、Cloneableオブジェクトのすべてのフィールドをその新しいインスタンス(プリミティブまたは参照)にコピーします。そのため、参照型の場合、参照ビットのみが新しいインスタンスにコピーされるため、両方のオブジェクトの参照変数は同じオブジェクトを指します。上記の例は、シャロークローニングの例です。

Deep Cloning名前が示すように、Deep Cloningは、あるオブジェクトから別のオブジェクトにすべてをクローンすることを意味します。これを実現するには、clone()メソッドをだまして独自のクローニング戦略を提供する必要があります。 Cloneableインターフェイスを実装し、オブジェクト階層にあるすべての参照型でclone()メソッドをオーバーライドしてから、super.clone()およびこれらのclone()メソッドを呼び出して、オブジェクトのcloneメソッド。

ただし、ソースコードでArrayListのclone()メソッドを見ると、v.elementData = Arrays.copyOf(elementData, size);を呼び出した後に外部でsuper.clone()をコピーしていることがわかります。つまり、ArrayListのclone()が深くコピーされていることを意味します内容

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

クローン作成、およびディープクローン作成やシャロークローン作成などのタイプの詳細については、 Javaクローン作成とクローン作成の種類(例の詳細にある浅いおよび深い) をお読みください。

1
Naresh Joshi

arraylistのclone関数は、あるarraylistを別のarraylistにコピーすることとは異なります。clone()を使用する場合、元のarraylistのコピーを保持しますが、clone()を使用した後に元のarraylistに変更を加えても、コピーされたarraylist ..例:

public static void main(String[] a) {

List list = new ArrayList();

list.add("A");

List list2 = ((List) ((ArrayList) list).clone());

System.out.println(list);
System.out.println(list2);

list.clear();

System.out.println(list);
System.out.println(list2);
}

出力:-

[A]

[A]

[]

[A]

0
Dahlia

このような文字列を追加する位置を動的に選択することはできません

int r=k.nextInt();
Integer i6=new Integer(r);
System.out.println("Enter the address");
String p6=k.nextLine();
ar3.add(i6,p6);

整数を読み取った後に実行しない

0
vijay