gajapathy p
gajapathy p

Reputation: 113

System.arraycopy() shallow copy or deepcopy with primitive and object references

I read somewhere that System.arraycopy does create a new copy for primitive data types and shallow copy for object references.

so, that I started the experiment that with below 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));

and the output was

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

But what I expected was

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

from the above code, I understood that System.arraycopy does deep copy for object references If so, how obj1[0] == obj2[0] gives true

Upvotes: 4

Views: 4513

Answers (4)

Vasu
Vasu

Reputation: 22442

I understood that System.arraycopy does deep copy for object references If so, how obj1[0] == obj2[0] gives true

No, you are wrong, it doesn't perform the deep copy. Because obj1[0] == obj2[0] refer the same integer objects (i.e., references stored in the arrays at index '0') inside the both the arrays, so you are getting the answer as true. Also, you can compare obj1[1] == obj2[1] which returns false, because both the StringBuffer references are different.

Also, the other point is that System.arrayCopy does only a shallow copy (simply copies the references/values from one array to another), you can refer here on this.

Upvotes: 0

Eran
Eran

Reputation: 393946

System.arraycopy does shallow copy, which means it copies Object references when applied to non primitive arrays.

Therefore after System.arraycopy(obj1,0,obj2,0,obj1.length);, obj1[0]==obj2[0] and obj1[1]==obj2[1], since both arrays hold references to the same Objects.

Once you assign a new value to obj1[1], obj1[1] no longer refers to the same StringBuffer instance as obj2[1]. That's why the outputs of Arrays.toString(obj1) and Arrays.toString(obj2) are different.

If instead of

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

you would write

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

both print statements would output [3, world], since both arrays would still refer to the same StringBuffer instance.

Upvotes: 4

RealSkeptic
RealSkeptic

Reputation: 34638

You have a misconception.

Once you do

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

You have replaced the reference in obj1[1]. Now the two arrays contain different references to different objects.

If you want to see that what was copied was the actual reference, you should try instead:

obj1[1].setLength(3);

Now both obj1[1] and obj2[1] should contain the string hel, because you did not replace the reference but rather changed the content.

Upvotes: 5

Kayaman
Kayaman

Reputation: 73568

No, it's shallow copy for references.

First you create the reference to a new StringBuffer("hello"), then you make a shallow copy of that. So you've got 1 StringBuffer, but 2 references to it.

Finally you replace the other reference with a completely new StringBuffer("world").

Upvotes: 1

Related Questions