How to understand the clone method of Java arrays more thoroughly

Keywords: Java

Say in front
Before we go into understanding clone, we need to have a clear understanding of the storage patterns of "basic data types" and "reference data types".

The basic data type, the content of the variable holds the actual value; referring to the data type, the content of the variable holds an address, and the direction of the address is the actual value.


    int baseData = 5;     // The basic data type, the memory corresponding to baseData, holds the specific value:5
    System.out.println(baseData); // Direct printing, return: 5
    
    HandClass handData = new HandClass(); //Referring to the data type, the memory corresponding to handData holds a hexadecimal memory address, which is where the value is stored.
    System.out.println(handData); //Print directly and return the memory address: HandClass@3c6f579

It should be noted that whether it is a basic data type or a reference data type, the assignment (=) operation assigns the content of the variable itself to another variable. The only difference is that in our common operations, the basic data type is for its own content (value), while the reference data type is for its own content (address) direction.

    int data1 = 1;
    int data2 = data1; // Assign the content of data 1 (1) to data2
    System.out.println(data1); // Return: 1
    System.out.println(data2); // Return: 1

    data1 = 2; // Even if you modify the contents of data1, data2 is unaffected

    System.out.println(data1); // Return: 2
    System.out.println(data2); // Return: 1

    System.out.println("--------------------");


    HandClass handData1 = new HandClass();
    handData1.ele = 1;
    HandClass handData2 = handData1; // Assign the content of handData1 (the actual memory address) to handData2
    System.out.println(handData1.ele); // Return: 1
    System.out.println(handData2.ele); // Return: 1

    // Print handData1 and handData2 directly and return the same content (address)
    System.out.println(handData1); // Return: HandClass@66edc3a2
    System.out.println(handData2); // Return: HandClass@66edc3a2

    handData1.ele = 2; // Modify the content of handData1.ele, which affects handData2 because they have the same content (pointing to the same memory)

    System.out.println(handData1.ele); // Return: 2
    System.out.println(handData2.ele); // Return: 2

    handData1 = new HandClass(); // Open up a new inland address for handData1 and assign it to the content of handData1

    // Print handData1 and handData2 directly and return different contents (addresses): the contents of handData1
    System.out.println(handData1); // Return: HandClass@3ced0338
    System.out.println(handData2); // Return: HandClass@66edc3a2

    handData1.ele = 3; // Modify the contents of handData1.ele again at this point, and handData2 is unaffected because their contents are already different (pointing to different memory)

    System.out.println(handData1.ele); // Return: 3
    System.out.println(handData2.ele); // Return: 2

Summary: Whether the basic data type or the reference data type, the essence of assignment operation is content assignment.

Getting down to business
First throw out the conclusion: the clone method of array is essentially "dimension reduction assignment". After reducing the dimension of the array, create a memory space exactly like it, and then perform traversal assignment.

(This article does not discuss the storage mode of arrays. For those who are weak in the storage mode of arrays, please understand for yourself first.)

One-dimensional arrays:
One-dimensional array is a set of variables after dimensionality reduction.

    int intArrayA[] = new int[]{1,2,3};
    int intArrayB[] = intArrayA.clone(); // Assigning clones of intArrayA to intArrayB
    /**
     * First, dimension reduction of intArray A is carried out.
     * After dimensionality reduction, it becomes a set of variables: int Array A [0], int Array A [1], int Array A [2]
     * Apply in memory for a set of arrays of the same type and length as intArray A: int tmp[] = new int[2];
     * Traversal assignment of variables: TMP [0] = int Array A [0], TMP [1] = int Array A [1], TMP [2] = int Array A [2]
     * Returns the content (address) of the array tmp (note: tmp is an array, that is, a reference type)
     * */
    System.out.println(intArrayA[1]);  // Return: 2
    System.out.println(intArrayB[1]);  // Return: 2

    intArrayA[1] = 100;

    System.out.println(intArrayA[1]);  // Return: 100
    System.out.println(intArrayB[1]);  // Return: 2
    /**
     * The above conclusion: "Whether the basic data type or the reference data type, the essence of assignment operation is content assignment. "
     * intArrayA After dimensionality reduction, intArray A [0]-intArray A [2] is a set of variables of basic data types.
     * When assigning values, the contents (actual values) of intArray A [0]-intArray A [2] are assigned to tmp[0]-tmp[2]
     * Then the content (an address) of the TMP consisting of tmp[0]-tmp[2] is returned to intArray B.
     * Therefore, the contents of intArray B [1] and intArray A [1] are identical, and their contents are "2"
     * When we operate through intArray A [1], we simply modify our content, and intArray B [1] will not be affected.
     * */

    System.out.println("--------------------");

    HandClass handArrayA[] = new HandClass[]{new HandClass(),new HandClass(),new HandClass()};
    HandClass handArrayB[] = handArrayA.clone();
    /**
     * Firstly, the dimension of handArray A is reduced.
     * After dimensionality reduction, program a set of variables: handArray A [0], handArray A [1], handArray A [2]
     * Apply in memory for a set of arrays of the same length as handArray A type: HandClass tmp[] = new HandClass[2];
     * Traversal assignment of variables: TMP [0] = handArray A [0], TMP [1] = handArray A [1], TMP [2] = handArray A [2]
     * Returns the content (address) of the array tmp (note: tmp is an array, that is, a reference type)
     * */

    System.out.println(handArrayA[1].ele);  // Return: 0 Note: 0 here is the default initial value assigned by the system when instantiated
    System.out.println(handArrayB[1].ele);  // Return: 0

    handArrayA[1].ele = 100;

    System.out.println(handArrayA[1]);  // Return: HandClass@7b1ddcde
    System.out.println(handArrayB[1]);  // Return: HandClass@7b1ddcde
    System.out.println(handArrayA[1].ele);  // Return: 100
    System.out.println(handArrayB[1].ele);  // Return: 100
    /**
     * The above conclusion: "Whether the basic data type or the reference data type, the essence of assignment operation is content assignment. "
     * handArrayA After dimensionality reduction, handArray A [0]-handArray A [2] is a set of variables of reference type.
     * When assigning, the content (an address) of handArray A [0]-handArray A [2] is assigned to tmp[0]-tmp[2]
     * Then the content (an address) of the TMP consisting of tmp[0]-tmp[2] is returned to handArray B.
     * Therefore, the contents of handArray B [1] and handArray A [1] are identical, and they all point to the same memory.
     * When we operate through handArray A [1] (actually modifying the content of the actual object corresponding to its content), handArray B [1] (the actual object to which the content refers) will also be affected.
     * */

Two-dimensional and multi-dimensional arrays:
After dimensionality reduction, a two-dimensional array is an array, and the array itself is a reference type. Therefore, the assignment in the cloning of two-dimensional and multi-dimensional arrays belongs to the assignment of reference type.

    int multIntArrayA[][] = new int[][]{{11,12,13},{21,22,23}};
    int multIntArrayB[][] = multIntArrayA.clone();
    /**
     * Firstly, the dimensionality of multInt Array A is reduced.
     * After dimensionality reduction, it becomes a set of one-dimensional arrays: multInt Array A [0], multInt Array A [1]
     * Apply for a set of arrays in memory of the same type and length as multIntArray: int tmp[][] = new int[2][3];
     * Traversal assignment of the array: tmp[0]=multIntArray[0], tmp[1]=multIntArray[1],
     * In particular, here is the assignment of an array (reference type), not an array element (int type).
     * Returns the content (address) of the array tmp (note: tmp is an array, that is, a reference type)
     * */

    System.out.println(multIntArrayA[0][1]); // Return: 12
    System.out.println(multIntArrayB[0][1]); // Return: 12

    multIntArrayA[0][1] = 66;

    System.out.println(multIntArrayA[0][1]); // Return: 66
    System.out.println(multIntArrayB[0][1]); // Return: 66
    /**
     * We note that multInt Array B has been affected by multInt Array A.
     * Because clone only reduces one dimension and then performs traversal assignment, that is, assigning the content (an address) of multIntArray A [0] to multIntArray B [0]
     * When we manipulate multIntArray A [0] [1], we actually manipulate the value of the first element of the actual array that the content of multIntArray A [0] points to.
     * multIntArrayB[0]Save the same content as multIntArray A [0], and point to the same array
     * So multIntArray B [0] [1] is all equal to multIntArray A [0] [1] (variable itself is identical)
     * Again, it can be made clear that clone's dimensionality reduction will only reduce one dimension.
     * To clone an array element, you need to clone again to reduce the dimension to an array element.
     * */

    multIntArrayB[0] = multIntArrayA[0].clone();

    multIntArrayA[0][1] = 77;

    System.out.println(multIntArrayA[0][1]); // Return: 77
    System.out.println(multIntArrayB[0][1]); // Return: 66
    /**
     * As you can see, when we clone multInt Array A [0].
     * multIntArrayA[0]After dimensionality reduction, it is a set of basic data type variables (int)
     * Therefore, each element in multInt Array B [0] (basic data type) is equal to the element in multInt Array A [0], but is a "clone".
     * When we modify multInt Array A [0] [1], multInt Array B [0] [1] will not change with it.
     * In order to enhance the validation of this phenomenon, we changed "basic data type" to "reference data type".
     * If our guess is correct, the final output should also be "77" instead of "66".
     * */

    System.out.println("--------------------");

    HandClass multHandArrayA[][] = new HandClass[][]{{new HandClass(),new HandClass(),new HandClass()},{new HandClass(),new HandClass(),new HandClass()}};
    HandClass multHandArrayB[][] = multHandArrayA.clone();



    System.out.println(multHandArrayA[0][1]); // Return: HandClass@7b1ddcde
    System.out.println(multHandArrayB[0][1]); // Return: HandClass@7b1ddcde

    multHandArrayA[0][1].ele = 66;

    System.out.println(multHandArrayA[0][1].ele); // Return: 66
    System.out.println(multHandArrayB[0][1].ele); // Return: 66

    multHandArrayB[0] = multHandArrayA[0].clone();

    multHandArrayA[0][1].ele = 77;

    System.out.println(multHandArrayA[0][1].ele); // Return: 77
    System.out.println(multHandArrayB[0][1].ele); // Return: 77
    /**
     * If you just clone multHandArray A, the "basic data type" is the same as the "reference data type"
     * But when we clone multHandArray A [0] again, the effect is different.
     * Since multHandArray A [0] is dimensionally reduced, it is an array of reference data types.
     * Therefore, the content of each element (reference data type) in multHandArray B [0] is identical to the corresponding element in multIntArray A [0], which points to the same address.
     * When we modify the value of multHandArray A [0] [1] (which actually modifies the actual object whose address the content points to), multHandArray B [0] [1] will also change.
     * */

Summary: In Java, clone of arrays only reduces the dimension once, and then opens up a new space to traverse all elements for assignment.

It is worth mentioning.
One-dimensional arrays, because dimensionality reduction is the basic element of arrays, so it looks like a "deep copy" is actually wrong. Only clone of one-dimensional array of basic data type is the effect of "deep copy"; clone of one-dimensional array of reference data type needs additional "object copy";
Two-dimensional or multi-dimensional arrays can be recursively clone d in lower dimensions (up to one dimension) to achieve the goal of "deep copy".

Posted by KyleVA on Tue, 10 Sep 2019 00:10:08 -0700