2011-01-04 9 views
18
ArrayList<Integer> a=new ArrayList<Integer>(); 
a.add(5); 
ArrayList<Integer> b=(ArrayList<Integer>)a.clone(); 
a.add(6); 
System.out.println(b.toString()); 

In dem obigen Stück Code, ich denke, clone() macht eine flache Kopie. So sollten b und a auf denselben Speicherort verweisen. Wenn ich jedoch b.toString() mache, lautet die Antwort nur 5. Warum wird 6 auch nicht angezeigt, wenn clone() eine flache Kopie erstellt?clone(): ArrayList.clone() Ich dachte, eine flache Kopie

Antwort

49

Flache Kopie bedeutet nicht, dass sie auf den gleichen Speicherort verweisen. Das wäre nur eine Aufgabe: List b = a;.

Klonen erstellt eine neue Instanz, die die gleichen Elemente enthält. Dies bedeutet, dass Sie zwei verschiedene Listen haben, deren Inhalt jedoch gleich ist. Wenn Sie den Status eines Objekts in der ersten Liste ändern, wird es in der zweiten Liste geändert. (Da Sie einen unveränderlichen Typ verwenden - Integer - können Sie dies nicht beobachten)

Sie sollten jedoch nicht clone() verwenden. Es funktioniert gut mit Sammlungen, aber im Allgemeinen gilt es als gebrochen. Verwenden Sie die Kopie-Konstrukteuren - new ArrayList(originalList)

+1

so lesen, was ist der Unterschied zwischen tiefer Kopie und flacher Kopie – TimeToCodeTheRoad

+1

ist es richtig zu sagen, dass ein Klon einer Liste erstellen nur wandelbar Klassenobjekte enthält, , ist eine Verschwendung. – TimeToCodeTheRoad

+1

@TimeToCodeTheRoad flache Kopie funktioniert genau wie Bozho erklärt, tiefe Kopie kopiert die ArrayList und ihre Elemente. –

5

Wenn es wurde wie man dachte, dann ist die clone Methode würde völlig nutzlos, weil in diesem Fall die folgenden Zeilen würde entsprechen:

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

Klonen ist - wie in realen Szenarien - ein Prozess zum Erstellen von zwei Entitäten mit genau den gleichen Eigenschaften (zum Zeitpunkt des Klonens).

Und wie Bozho erwähnt - vermeiden Sie das Java clone() Konzept. Sogar der Autor hat erwähnt, dass es kaputt ist.

This question and it's answers sind sehr wertvoll und einen Link zu Josh Blochs besitzen Kommentare zu seinem Stück Arbeit ;-)

0

können wir nicht dynamisch zu wählen welche Position wir die Zeichenfolge wie folgt

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

sein nicht die Executing nach den ganzzahligen Lesen

0

Klon-Funktion in Arraylist ist nicht dasselbe wie das Kopieren einer Arraylist zum anderen, wenn wir Klon() verwenden, ist es die Kopie der Original-Arraylist hält, aber wenn wir machen jede Änderung t o die ursprüngliche arraylist nach dem Gebrauch clone(), wird es nicht die kopierte arraylist beeinflussen. ZB:

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); 
} 

Ausgang: -

[A]

[A]

[]

[A]

0

Diese in der Tat hat eine flache Kopie , hier ist ein Kommentar für Klon, aus ArrayList Quellcode

Gibt eine flache Kopie dieser ArrayList-Instanz zurück. (Die Elemente selbst werden nicht kopiert.)

Um dies zu verstehen, wollen wir uns ein Snippet in Klon-Methode suchen von Arraylist

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

Wie wir wissen, wenn wir ein Objekt auf eine Variable, JAVA zuweisen macht keine brandneue Kopie von dieses Objekt. Stattdessen wird diese Variable zu einer anderen Referenz, die auf das ursprüngliche Objekt verweist.

Daher speichert ElementData tatsächlich Referenz auf Objekte in dieser ArrayList. Und klonen Sie einfach kopieren Sie diese Referenzen, keine Repliken von Objekten erstellt werden.

Natürlich können Sie einen neuen Verweis auf eine geklonte ArrayList entfernen oder hinzufügen.

Die Änderung alter Objekte in einer ArrayList wirkt sich jedoch auf die ursprüngliche ArrayList aus. Es ist schwierig, Illustrationen mit Ihrem Beispiel zu erstellen, da Integer unveränderlich ist.

den Nebeneffekt zu sehen, können Sie eine benutzerdefinierte veränderbares Objekt

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); 
     } 
    } 

Dann definieren Sie den folgenden Code verwenden können Test

 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); 

Der Ausgang

sein sollte machen

tt: [0, 12]
yy: [12]

Sehen Sie die Nebenwirkung :)? Wir ändern nur das Element in yy, aber es spiegelt sich auch in tt wider.

1

Flaches Klonen ist die Standardklonierungsstrategie, die von Object.clone() bereitgestellt wird, von der Sie sprechen. Die Methode clone() der Objektklasse erstellt eine neue Instanz und kopiert alle Felder des Cloneable-Objekts in diese neue Instanz (entweder primitiv oder Referenz). Bei Referenztypen werden also nur Referenzbits in die neue Instanz kopiert, daher wird die Referenzvariable beider Objekte auf das gleiche Objekt zeigen. Das Beispiel, das wir oben gesehen haben, ist ein Beispiel für Flachklonen.

Tiefklonen Wie der Name vermuten lässt, bedeutet tiefes Klonen, alles von einem Objekt auf ein anderes Objekt zu klonen.Um dies zu erreichen, müssen wir unsere clone()-Methode austricksen, um eine eigene Klonierungsstrategie bereitzustellen. Wir können dies tun, indem wir die Schnittstelle Cloneable implementieren und die Methode clone() in jedem Referenztyp, den wir in unserer Objekthierarchie haben, überschreiben und dann die Methoden super.clone() und clone() in der Klonmethode unseres Objekts aufrufen.

Aber wenn man sich die clone() -Methode von Arraylist in den Quellcode schauen, sehen Sie es von außen ist das Kopieren v.elementData = Arrays.copyOf(elementData, size); nach super.clone() Aufruf, was bedeutet, clone() von Arraylist tief kopiert Inhalt

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); 
    } 
} 

um mehr über Klonen und seine Typen wie tief das Klonen und flach Klonen lesen sie bitte Java Cloning and Types of Cloning (Shallow and Deep) in Details with Example

Verwandte Themen