Undesrstanding clone method for arrays

646 Views Asked by At

I've learnt that for arrays the clone method is well-behaved and we can use it. But I thought that the type of the elemetns the arrays hold should have implemented Cloneable interface. Let me provide some example:

public class test {

    public static void main(String[] args){
        Test[] arr_t = new Test[1];
        arr_t[0] = new Test(10);
        Test[] an_arr = arr_t.clone(); 
        an_arr[0]= new Test(5);
        System.out.println(an_arr[0].test); //5
        System.out.println(arr_t[0].test);  //10
    }

    public static class Test{
        public int test;
        public Test(int test) {
            this.test = test;
        }
    }
}

DEMO

I thought that 5 should have been printed twice. The reason for that is by clonning arrays we're creating new arrays containing references to the objects the first array holded (Because the type of the elemnts does not implement Cloneable). Couldn't you straighten the things out?

It's not clear if it's neccesary the array element's type implements Cloneable.

4

There are 4 best solutions below

3
On

It's a simple concept, but seems hard to explain. When you clone the array, you will have two district arrays in memory, but with the same values in their indexes.


In your second array an_arr doing an_array[0] = new Test(5) you will put another reference in the slot 0.

But the index 0 of the clone is in a different place from the cloned array.

Your example is valid if you do

Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = arr_t.clone(); 
an_arr[0].test = 5; // look here, I changed the object
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test);  //5

Now both will print the same value because they hold the same reference to the same object, but the place where this reference is stored, is different.

0
On

.clone() makes what's called a "shallow copy". That means it copies as little as possible when running the method; instead of copying the contents of the array, it just creates references to the contents of the original array.

If you change the references by calling:

new Test(5)

Then you've overwritten that reference, and get new data.

The alternative is a deep copy of the array. Those can be expensive to do on bigger objects, so they're not the default.

0
On

An array's clone() does the same thing regardless of type of array: it creates a new array of the same type and size and then it assigns (=) each element of array to each element of the new array. That's it.

So if you have a 3-element array pointed to by arr, and arr.clone() returns newArr, then after the creation of the new array it simply does this:

newArr[0] = arr[0];
newArr[1] = arr[1];
newArr[2] = arr[2];

That's it. The type of array is not relevant. There is no "cloning" or anything involved in the elements. It doesn't know (or care) if the element has some kind of method to clone (in fact, there is no general API for cloning in Java, anyway, so this would be impossible).

(And by the way, even if it somehow put cloned objects into the new array, the result in your example would still be the same, because you are assigning a new value into the array, so it doesn't matter what was there before.)

So your question is basically why:

Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = new Test[1];
an_arr[0] = arr_t[0]; 
an_arr[0] = new Test(5);
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test);  //10

and you can figure it out from there.

0
On

The "problem" here is that arrays hold references to object, not objects. Further, this has nothing to do with cloning.

When you execute:

an_arr[0] = new Test(5);

You are assigning the new object's reference to the first element.

Also, each array has its own references to Test objects. When you clone the array, only the references are copied (not the objects to which they refer).