当前位置: 首页 > 面试题库 >

如何在Java中克隆多维数组?

姬振濂
2023-03-14
问题内容

编辑2:以下是基于DuffyMo响应的代码段,该段代码说明了如何解决使用System.arraycopy多维数组克隆的局限性。

import java.util.Arrays;

public class Randar {
public static int[][] arrayMaster = {{6,1}, {10,1}, {1,1}};
private static int[][] arrayChanges = new int[arrayMaster.length][2];

public Randar () {

}
public static void main(String[] args) {
    arrayChanges[0][0] = 0;
    resetArrays(arrayChanges, arrayMaster);
    arrayChanges[0][0] = 0;

    System.out.format("arrayMaster: %s, arrayChanges: %s", Arrays.deepToString(arrayMaster), Arrays.deepToString(arrayChanges));
}


public static void resetArrays(int[][] arrayChanges, int[][] arrayMaster) {
for (int a=0; a< arrayMaster.length; a++) {
System.arraycopy(arrayMaster[a], 0, arrayChanges[a], 0, arrayMaster[a].length);
}
// arrayChanges = arrayMaster.clone(); will NOT work as expected
}
}

[原始问题]在Java中(完全)克隆多维数组的简单方法是什么?该程序说明了我的问题。

import java.util.Arrays;

public class Randar {
public static int[][] arrayMaster = {{6,1}, {10,1}, {1,1}};
static private int[][] arrayChanges = arrayMaster;

public static void main(String[] args) {
    arrayChanges[0][0] = 0;
    resetArrays();

    System.out.format("arrayMaster: %s, arrayChanges: %s",Arrays.deepToString(arrayMaster), Arrays.deepToString(arrayChanges));
}


public static void resetArrays() {
arrayChanges = arrayMaster.clone();
}

}

运行上面的代码时,与我的意图相反,arrayMaster以及arrayChanges都发生了变化。考虑到我可以克隆arrayMaster的每个一维数组成员,因此尝试解决此问题:

for (int iter = 0; iter < arrayMaster.length; iter++) {
    arrayChanges[iter] = arrayMaster[iter].clone();
    }

但是当我运行出于某种原因给出NullPointerException的代码时。编写循环遍历数组各个整数值的方法是我唯一的选择吗?

谢谢。

编辑1:这也不能解决问题。

import java.util.Arrays;

public class Randar {
public int[][] arrayMaster = {{6,1}, {10,1}, {1,1}};
private int[][] arrayChanges = arrayMaster.clone();

public Randar () {

}
public static void main(String[] args) {
    Randar Randar1 = new Randar();
    Randar1.arrayChanges[0][0] = 0;
    resetArrays(Randar1.arrayChanges, Randar1.arrayMaster);
    Randar1.arrayChanges[0][0] = 0;

    System.out.format("arrayMaster: %s, arrayChanges: %s",     Arrays.deepToString(Randar1.arrayMaster), Arrays.deepToString(Randar1.arrayChanges));
}


public static void resetArrays(int[][] arrayChanges, int[][] arrayMaster) {
/*for (int a=0; a< arrayMaster.length; a++) {
System.arraycopy(arrayMaster[a].clone(), 0, arrayChanges[a], 0, arrayMaster[a].length);
} */
arrayChanges = arrayMaster.clone();
}
}

问题答案:

运行上面的代码时,与我的意图相反,arrayMaster以及arrayChanges都发生了变化。

线

static private int[][] arrayChanges = arrayMaster;

是罪魁祸首。该行指向arrayChangesarrayMaster指向同一对象,因此当您从任一对象访问该对象时,都可以看到对任一对象的更改。

编辑:每当您克隆多维数组的一个维度时会发生什么

正如Eric
Lippert解释的那样
,数组在概念上是变量列表。如果仅分配另一个变量以指向la相同的数组static private int[][] arrayChanges = arrayMaster;,则根本不会更改变量集。除了之外arrayChanges,您没有创建任何新变量,因此您没有从操作系统/
JVM中获得更多的内存,因此您所做的任何更改都将arrayMaster应用于该变量,arrayChanges反之亦然。

现在让我们看一个二维数组。在Java中,二维数组是一列变量的列表,这些变量恰好具有这些变量中的每个变量都指向一维数组的属性。因此,每当克隆一个二维数组时,都会创建一个新的变量列表,每个变量都指向旧变量所指向的相同位置。因此,您获得了一些arrayChanges[0] = new int[10]好处arrayMaster,可以安全地编写而不影响,但是一旦开始引用,arrayChanges[i][j]您仍在引用与该引用相同的第二级数组arrayMaster。要深度复制一个int的二维数组,您真正想要的是

public static int[][] deepCopyIntMatrix(int[][] input) {
    if (input == null)
        return null;
    int[][] result = new int[input.length][];
    for (int r = 0; r < input.length; r++) {
        result[r] = input[r].clone();
    }
    return result;
}

对于那些将来可能会看这个答案的人:是的,最好intT这里代替并使该方法通用,但是为此目的,更具体的深度复制方法更易于解释。



 类似资料:
  • 问题内容: 有没有一种方法可以克隆的实例而无需将其字符串化并重新解析结果? 浅表副本是可以接受的。 问题答案: 使用构造函数和方法。

  • 问题内容: 我有一个我想退还的副本。 有一个具有以下签名的克隆方法: 调用此方法后,如何将返回的对象强制转换回? 问题答案:

  • 问题内容: 如何克隆 Java并同时在Java中克隆其项目? 例如,我有: 我希望其中的对象与狗列表中的对象不同。 问题答案: 你将需要迭代这些项目,然后逐个克隆它们,然后将克隆放入结果数组中。 显然,要使该方法起作用,你将必须使你的类实现接口并重写该方法。

  • 问题内容: 需要一个将克隆Oracle用户的sql查询。作为源,我拥有拥有所有必要特权的用户。我想知道是否可以创建相同的数据库,但在同一数据库中使用不同的用户名。 问题答案: 简要地(从这里开始) 然后,只需将用户名替换为您要创建的新用户名即可。

  • 问题内容: 我有一个其中包含许多bufferedimages的对象,我想创建一个新对象,将所有bufferedimages复制到新对象中,但是这些新图像可能会更改,并且我不希望通过更改原始对象图像来更改新对象图像。 明白了吗? 这有可能做到吗,有人可以建议一个好方法吗?我曾经想到过getSubImage,但在某处阅读过,该子映像的任何更改都被重新关联回了父映像。 我只希望能够获得BufferedI

  • 我试图在RecyclerView使用的ArrayList中创建一个对象的克隆,我已经用Clonable扩展了我的实体,但是当我编辑克隆的对象时,甚至修改了原始对象。 什么将是正确的方式来克隆/复制一个对象在回收器视图? 实体: 实体变量: 活动: 然后,当一个RecyclerView项目被滑动时,将该位置传递到一个修改对话框,在该对话框中,我可以对该对象进行一些编辑。 编辑: 通过深入研究,我发现