2017-04-05 4 views
1

J'ai lu quelque part que System.arraycopy crée une nouvelle copie pour les types de données primitifs et une copie superficielle pour les références d'objet.System.arraycopy() copie superficielle ou copie profonde avec des références de primitives et d'objets

donc, que j'ai commencé l'expérience que, avec ci-dessous le 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)); 

et la sortie était

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

Mais ce que je pensais était

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

du code ci-dessus, J'ai compris que System.arraycopy fait une copie profonde pour les références d'objet Si oui, comment obj1[0] == obj2[0] donne true

+0

"Copie en profondeur pour les primitives". Comment pouvez-vous faire une copie profonde pour les primitifs, alors que par définition, ils ne se réfèrent à rien de plus profond? – RealSkeptic

Répondre

2

Vous avez une idée fausse.

Une fois que vous faites

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

Vous avez remplacé la référence dans obj1[1]. Maintenant, les deux tableaux contiennent des références différentes à différents objets.

Si vous voulez voir que ce qui a été copié était la référence réelle, vous devriez essayer à la place:

obj1[1].setLength(3); 

Maintenant, les deux obj1[1] et obj2[1] doit contenir la chaîne hel, parce que vous ne l'avez pas remplacé la référence, mais plutôt a modifié le contenu.

+0

Maintenant, j'ai compris. explication claire .. –

1

System.arraycopy ne copie peu profonde, ce qui signifie que des copies Object références lorsqu'il est appliqué à des réseaux non primitifs.

Par conséquent, après System.arraycopy(obj1,0,obj2,0,obj1.length);, obj1[0]==obj2[0] et obj1[1]==obj2[1], puisque les deux tableaux contiennent des références à la même Object s.

Une fois que vous affectez une nouvelle valeur à obj1[1], obj1[1] ne fait plus référence à la même instance StringBuffer que obj2[1]. C'est pourquoi les sorties de Arrays.toString(obj1) et Arrays.toString(obj2) sont différentes.

Si au lieu de

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

vous écririez

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

les deux déclarations d'impression génèrerait [3, world], puisque les deux tableaux se réfèrent toujours au même StringBuffer exemple.

0

Non, c'est une copie superficielle pour les références.

D'abord, vous créez la référence à new StringBuffer("hello"), puis vous en faites une copie superficielle. Donc vous avez 1 StringBuffer, mais 2 références.

Enfin, vous remplacez l'autre référence par un new StringBuffer("world") complètement.

+0

Si oui 'obj1 == obj2' devrait donner vrai? Mais ça donne 'false' –

+0

Non, ce ne sont pas des références au tableau ** same **, donc ça renvoie faux bien sûr. – Kayaman

0

Je compris que System.arraycopy ne copie en profondeur pour objet références Si oui, comment obj1 [0] == obj2 [0] donne vrai

Non, vous avez tort, il n » t effectuer la copie profonde. Car obj1[0] == obj2[0] référencez les mêmes objets entiers (c'est-à-dire, les références stockées dans les tableaux à l'index '0') à l'intérieur des deux tableaux, de sorte que vous obtenez la réponse true. Aussi, vous pouvez comparer obj1[1] == obj2[1] qui renvoie false, car les deux références StringBuffer sont différentes.

L'autre point est que System.arrayCopy fait seulement une copie superficielle (copie simplement les références/valeurs d'un tableau à un autre), vous pouvez vous référer à here sur ceci.

+0

'obj1 [0] == obj2 [0] compare les valeurs entières' - en fait c'est faux. 'obj1 [0]' et 'obj2 [0]' font référence au même objet 'Integer' en résultat de l'instruction arraycopy, ce qui explique pourquoi' obj1 [0] == obj2 [0] '. Si vous ajoutez un 'obj2 [0] = new Integer (3);' après l'instruction arraycopy, 'obj1 [0] == obj2 [0]' ne sera plus vrai, même si les deux auront toujours la même valeur (3). – Eran

+0

Merci Eran, j'ai corrigé – developer