Why does Array.copyOf() mutate the original array in case of 2D Arrays?

后端 未结 2 1251
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-23 13:39

If I create a 2D int array in Java, and then make a copy of it using Arrays.copyOf(), like so -

jshell> int[][] c1 = {{1,2}, {3,4}}
c         


        
相关标签:
2条回答
  • 2021-01-23 14:02

    Method Arrays.copyOf does not perform a deep copy of an array, nor does System.arraycopy method. You should implement the algorithm of deep copy of the array yourself with the required copy depth. For example:

    int[][] arr1 = {{1, 2}, {3, 4}};                 // original array
    int[][] arr2 = Arrays.copyOf(arr1, arr1.length); // shallow copy
    int[][] arr3 = Arrays.stream(arr1)               // deep copy
            .map(Arrays::stream)
            .map(IntStream::toArray)
            .toArray(int[][]::new);
    
    arr1[0][0] = 7;
    
    System.out.println(Arrays.deepToString(arr1)); // [[7, 2], [3, 4]]
    System.out.println(Arrays.deepToString(arr2)); // [[7, 2], [3, 4]]
    System.out.println(Arrays.deepToString(arr3)); // [[1, 2], [3, 4]]
    

    And the same is true for an array of objects:

    public class Test {
        public static void main(String[] args) {
            SomeObject[] arr1 = {                                 // original array
                    new SomeObject(1),
                    new SomeObject(2),
                    new SomeObject(3),
                    new SomeObject(4)};
            SomeObject[] arr2 = Arrays.copyOf(arr1, arr1.length); // shallow copy
            SomeObject[] arr3 = Arrays.stream(arr1)               // deep copy
                    .mapToInt(SomeObject::getField)
                    .mapToObj(SomeObject::new)
                    .toArray(SomeObject[]::new);
    
            arr1[0].setField(7);
    
            System.out.println(Arrays.toString(arr1)); // [7, 2, 3, 4]
            System.out.println(Arrays.toString(arr2)); // [7, 2, 3, 4]
            System.out.println(Arrays.toString(arr3)); // [1, 2, 3, 4]
        }
    
        static class SomeObject {
            int field;
    
            public SomeObject(int field) { this.field = field; }
    
            public int getField() { return field; }
    
            public void setField(int field) { this.field = field; }
    
            public String toString() { return String.valueOf(field); }
        }
    }
    
    0 讨论(0)
  • 2021-01-23 14:12

    A 2D array is basically an array that contains arrays, and Arrays.copyOf does a shallow copy, so only the outer array (the array of arrays) is copied, not the values inside the array (in this case, arrays of int, ie int[]). As a result, both the original and the copy contain the same int[] arrays, so if you modify through one, the result is also visible through the other.

    This is explicitly mentioned in the javadoc:

    For all indices that are valid in both the original array and the copy, the two arrays will contain identical values.

    You do need to read that with the knowledge of the signature: <T> T[] copyOf(T[], int). The array copied is T[] (an array of T, where T is int[]), not T[][]!

    For a deep copy of a 2D array, you will have to deep copy the array yourself, for example see How do I do a deep copy of a 2d array in Java?

    0 讨论(0)
提交回复
热议问题