2017-04-05 1 views
1

Ich habe irgendwo gelesen, dass System.arraycopy erstellt eine neue Kopie für primitive Datentypen und flache Kopie für Objektreferenzen.System.arraycopy() flache Kopie oder deepcopy mit primitiven und Objektreferenzen

so begann, dass ich das Experiment, das mit folgendem Code

//trying with primitive values 
int a[] ={1,2,3}; 
int b[] = new int[a.length]; 
System.arraycopy(a,0,b,0,a.length); 
b[0] = 9; 
System.out.println(Arrays.toString(a)); 
System.out.println(Arrays.toString(b)); 
//now trying with object references 
Object[] obj1 = {new Integer(3),new StringBuffer("hello")}; 
Object[] obj2 = new Object[obj1.length]; 
System.arraycopy(obj1,0,obj2,0,obj1.length); 
obj1[1] = new StringBuffer("world"); 
System.out.println(Arrays.toString(obj1)); 
System.out.println(Arrays.toString(obj2)); 

und der Ausgang

[1, 2, 3] 
[9, 2, 3] 
[3, world] 
[3, hello] 

war Aber was erwartete ich war

[1, 2, 3] 
[9, 2, 3] 
[3, world] 
[3, world] 

aus dem obigen Code, Ich habe verstanden, dass System.arraycopy tiefe Kopie für Objektreferenzentut Wenn 10 so, wie obj1[0] == obj2[0] gibt true

+0

"Deep-Kopie für Primitive". Wie können Sie eine tiefe Kopie für Primitive machen, wenn sie sich per definitionem nicht auf etwas tieferes beziehen? – RealSkeptic

Antwort

2

Sie haben ein Missverständnis.

Sobald Sie

tun
obj1[1] = new StringBuffer("world"); 

Sie haben ersetzt die Referenz in obj1[1]. Jetzt enthalten die beiden Arrays unterschiedliche Referenzen auf verschiedene Objekte.

Wenn Sie sehen wollen, dass das, was kopiert wurde die tatsächliche Referenz war, sollten Sie versuchen, statt:

obj1[1].setLength(3); 

beide nun obj1[1] und obj2[1] sollte die Zeichenfolge hel enthalten, da Sie nicht die Referenz ersetzen hat, sondern eher änderte den Inhalt.

+0

Jetzt verstand ich. klare Erklärung .. –

1

System.arraycopy tut flache Kopie, die es Kopien Object Referenzen bedeutet, wenn sie nicht primitiven Arrays angewendet.

Daher nach System.arraycopy(obj1,0,obj2,0,obj1.length);, obj1[0]==obj2[0] und obj1[1]==obj2[1], da beide Arrays Referenzen auf die gleichen Object s halten.

Sobald Sie obj1[1] einen neuen Wert zuweisen, bezieht sich obj1[1] nicht mehr auf die gleiche StringBuffer Instanz wie obj2[1]. Aus diesem Grund sind die Ausgänge Arrays.toString(obj1) und Arrays.toString(obj2) unterschiedlich.

Wenn statt

obj1[1] = new StringBuffer("world"); 

Sie

Aussagen
obj1[1].setLength(0); 
obj1[1].append("world"); 

beide Druck schreiben würde ausgeben würde [3, world], da beide Arrays immer noch auf die gleiche StringBuffer Instanz verweisen würde.

0

Nein, es ist flache Kopie für Referenzen.

Zuerst erstellen Sie den Verweis auf eine new StringBuffer("hello"), dann erstellen Sie eine flache Kopie davon. Sie haben also 1 StringBuffer, aber 2 Verweise darauf.

Schließlich ersetzen Sie die andere Referenz durch eine vollständige new StringBuffer("world").

+0

Wenn ja, obj1 == obj2 sollte wahr richtig geben? Aber es gibt "false" –

+0

Nein, sie sind nicht Verweise auf die ** gleichen ** Array, so dass natürlich zurückkehrt. – Kayaman

0

Ich verstand, dass System.arraycopy für Objekt tiefe Kopie tut Referenzen Wenn ja, wie obj1 [0] == obj2 [0] wahr gibt

Nein, Sie sind falsch, es doesn‘ t führen Sie die tiefe Kopie durch. Weil obj1[0] == obj2[0] die gleichen Integer-Objekte referenzieren (d. H. In den Arrays gespeicherte Referenzen auf Index '0') innerhalb der beiden Arrays, so erhalten Sie die Antwort true. Sie können auch obj1[1] == obj2[1] vergleichen, die false zurückgibt, weil beide StringBuffer Referenzen unterschiedlich sind.

Der andere Punkt ist, dass System.arrayCopy nur eine flache Kopie (kopiert einfach die Referenzen/Werte von einem Array zu einem anderen), können Sie auf 10 verweisen.

+0

'obj1 [0] == obj2 [0] vergleicht die Integer-Werte - eigentlich ist das falsch. 'obj1 [0]' und 'obj2 [0]' beziehen sich auf das gleiche 'Integer'-Objekt als Ergebnis der arraycopy-Anweisung, weshalb' obj1 [0] == obj2 [0] '. Wenn Sie ein 'obj2 [0] = new Integer (3);' nach der Arraycopy-Anweisung hinzufügen, ist 'obj1 [0] == obj2 [0] 'nicht mehr wahr, obwohl beide immer noch den gleichen Wert haben (3). – Eran

+0

Danke Eran, korrigierte ich – developer

Verwandte Themen