为什么这个Java操作会影响我程序中的多个变量?

时间:2016-10-10 01:19:45

标签: java

在我的方法开始时,我创建了两个2d列表数组。

public int[][] acds(int[][] board, ArrayList<Integer>[][] domains ) throws Exception {

    ArrayList<Integer>[][] domainsLeft  = new ArrayList[9][9];
    ArrayList<Integer>[][] domainsRight = new ArrayList[9][9];

我使用以下代码填充这些数组:

    for (int r = 0; r < 9; r++)
        for (int c = 0; c < 9; c++) {
            domainsLeft[r][c] = domains[r][c];
            domainsRight[r][c] = domains[r][c];
        }

然后,我根据特定列表的大小找到一个分区点。

    int initLength = domains[rIndex][cIndex].size();
    int splitPoint = (initLength / 2);

然后我遍历并从一个数组的前半部分中删除项目,并从第二个数组的后半部分中删除项目。

    for (int i = 0; i < initLength; i++) {
        if (i < splitPoint) {
            domainsLeft[rIndex][cIndex].remove(0);//<--HERE
        } else {
            domainsRight[rIndex][cIndex].remove(splitPoint); //<--HERE
        }
    }

我的问题是,当我单步执行代码时,上面注释的行(即删除)似乎会删除所有三个列表中的值(即domains[rIndex][cIndex]domainsLeft[rIndex][cIndex]和{{ 1}})。

我用Java编程已经有一段时间,但我的理解是每个粗体线应该只影响调用方法的列表(即domainsRight[rIndex][cIndex]domainsLeft[rIndex][cIndex] - 但不是两者)。

有人知道为什么会这样吗?我错过了什么......?

如果可能有帮助,我可以发布截图。感谢

2 个答案:

答案 0 :(得分:1)

问题是Integer不是int

Integer是一个对象,其中基本类型int存储在拳击中。

intprimitive_type,您可以使用'='运算符进行分配。

作为每个对象,每个Integer都有一个地址,并且通过执行:

 domainsLeft[r][c] = domains[r][c];
 domainsRight[r][c] = domains[r][c];

您要分配地址,而不是对象。 所以现在当你改变其中一个时,另一个也会改变。基本上它是“两个地方”中的同一个对象。

你会想要克隆它,或者以其他方式改变你的方法。

由于Integer不是一个复杂的对象,您可以重新选中每个int值进行克隆。

domainsLeft[r][c] = Integer.valueOf((domains[r][c]).intValue());
//...

答案 1 :(得分:1)

你正面临着问题,因为在这里你正在进行浅层复制,这意味着我们只需要指定引用,这样就可以指出相同的位置,无论我们做什么改变,它都会反映在那里。

如果我们通过一个例子来学习,那就更好了。

System.out.println(domainsLeft[0][0]);
System.out.println(domainsRight[0][0]);

输出结果为:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

List list = new ArrayList();     list.addAll(domainsRight [0] [0]); //深度克隆

List<Integer> oldList = domainsRight[0][0];
if(oldList.size() > 0){
    oldList.remove(0);
}

这里我们先做两件事,我们从数组中的列表中创建新的arraylist。第二,我们从数组中的列表中删除一个元素。

    System.out.println(domainsLeft[0][0]);
    System.out.println(domainsRight[0][0]);
    System.out.println(list);

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

所以在这里我们可以看到,当我们从domainsLeft中的列表中删除元素时,它从所有引用中删除但不是使用new运算符创建的列表形式,因为它是使用深度克隆[我们不使用引用]创建的。