【问题标题】:Cloning multi-dimensional arrays克隆多维数组
【发布时间】:2013-04-17 15:48:47
【问题描述】:
int[][] array = new int[][] {...}
int[][] clone = array.clone();

我天真地以为这会奏效。但它没有——它只克隆了第一个维度,如果我想要一个真正的克隆,我必须手动去克隆另一个维度。注意:内容已正确复制。但是当我更改clone[0][1]时,它反映在array[0][1]中

虽然已知.clone() 执行浅克隆,但int[][] 看起来像一个单独的对象(至少如果我们不知道它的内部实现)

为什么选择这种行为? int[][] 不是引用数组对象,而不仅仅是数组的第一个维度吗?在什么情况下只克隆第一维所需的行为?

【问题讨论】:

    标签: java


    【解决方案1】:

    我实际上无法复制您提到的行为。我可以看到一些答案提到浅拷贝是问题的根本原因。如果我错了,请纠正我,浅拷贝只是意味着在克隆时我们将获得引用的副本,而不是对象的副本。一个很好的解释可以在这里找到In Java, what is a shallow copy?

    在这种情况下,浅拷贝只会确保原始数组中的更改会反映在克隆的数组中,但不会阻止任何内容被复制。

    int[][] array = new int[][] {{1,2,3},{4,5,6}, {7,8,9}};
    int[][] clone = array.clone();
    
    //Try this to see magic of shallow copy
    //array[2][1]=11;
    
    for(int i=0;i<array.length;i++)
        for(int j=0;j<array[i].length;j++)
            System.out.println("array["+i+"]["+j+"]"+array[i][j]);
    
    for(int i=0;i<clone.length;i++)
        for(int j=0;j<clone[i].length;j++)
            System.out.println("clone["+i+"]["+j+"]"+clone[i][j]);
    

    对我来说,克隆非常完美,即两个数组具有相同的内容。我能想到得到克隆数组不会显示某些信息的问题的唯一原因是我们实际上在克隆后修改了原始数组(然后是浅拷贝)。

    顺便说一句,我使用的是 Java 1.6,我希望这不是问题。

    编辑:如果我们只需要了解为什么它们是多维数组的浅拷贝而不是深拷贝。让我们看两个事实

    1. 在克隆时,对象总是被克隆为浅拷贝(对象引用的拷贝),只有本机类型才会得到真正的拷贝。 In Java, what is a shallow copy?
    2. java中的数组其实是一个对象Is an array an object in java

    现在结合1和2,我们知道Java中的多维数组只是一个对象,它具有其他数组对象的引用。

    类似 ArrayObj->{ArrayObj, ArrayObj, ArrayObj};

    因为我们在对象(组合)中有对象,所以我们应该根据 Java 克隆规则获得浅拷贝。

    【讨论】:

    • 我会澄清的。克隆确实发生了,但并不深。
    【解决方案2】:

    clone 方法是所谓的浅拷贝(参见another stackoverflow answer on the clone method),这意味着所有元素都是通过引用复制的。

    要获得您想要的(也称为深度克隆),您可以使用Arrays.copy 递归地自己复制每个数组,这样您找到的每个(子)数组都会得到一个深度克隆,或者检查@987654322 @。

    黑客愉快:-)

    【讨论】:

      【解决方案3】:

      因为没有真正的多维数组,所以演示了这种行为。

      Java 通过制作数组的数组来实现多维。这意味着:

      int[][] is actually Array<Array<int>>
      

      因此克隆只会复制第一个维度。

      如果您尝试使用 3 维数组,则需要克隆三次。

      【讨论】:

        【解决方案4】:

        为什么选择这种行为?

        一致性,很有可能。

        正如你所说,int[][] 引用了一个数组对象。碰巧每个数组元素的内容都是另一个数组,但这只是一个细节。 Java 以相同的方式克隆所有数组,并且由于元素可以是任何类型,因此不能保证执行深度复制。

        因此clone() 对数组执行浅拷贝,因此只克隆第一个维度。

        (一般来说,对于克隆意味着深拷贝还是浅拷贝的问题,似乎没有单一的“最佳”或“明显”答案。开发人员想要什么取决于每个字段是如何使用的应用程序,所以一刀切的方法自然会有局限性。)

        【讨论】:

          猜你喜欢
          • 2018-02-11
          • 2021-10-23
          • 2021-10-06
          • 2011-01-18
          • 2018-11-04
          • 2013-10-31
          • 2012-02-24
          相关资源
          最近更新 更多