【问题标题】:Why does the method change the input parameter (array), despite the fact that I copy it inside the method?为什么该方法会更改输入参数(数组),尽管我将它复制到方法中?
【发布时间】:2020-04-25 16:42:18
【问题描述】:

我是 Java 新手。我有一个方法应该返回一个新的修改数组。但是在执行代码之后,作为参数的数组也发生了变化。请解释我在哪里修改原始数组。如何解决这个问题?我很绝望,因为我不明白我在哪里传递链接而不是值。

import java.util.Arrays;

public class question {

    public static void main(String[] args) {

        final int[][] inputArray = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        System.out.println("Original array:");
        System.out.println(Arrays.deepToString(inputArray));
        //Display
        //[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

        System.out.println("Array after delete line:");
        System.out.println(Arrays.deepToString((removeLine(1, inputArray))));
        //Display - ok
        //[[1, 2, 3], [7, 8, 9], [0, 0, 0]]


        System.out.println("The original array after using in method:");
        System.out.println(Arrays.deepToString(inputArray));
        //Display
        //[[1, 2, 3], [4, 5, 6], [0, 0, 0]]
        //I don't understand this.
    }

    static int[][] removeLine(int k, int[][] inpArray) {

        //I copy in resultArray to keep unchanged inpArray.
        int[][] resultArray = new int[inpArray.length][inpArray[0].length];
        System.arraycopy(inpArray, 0, resultArray, 0, inpArray.length);

        //I change resultArray.
        for (int i = k; i < resultArray.length - 1; i++) {
            resultArray[i] = Arrays.copyOf(resultArray[i + 1], resultArray[i + 1].length);
        }
        Arrays.fill(resultArray[resultArray.length - 1], 0);

        //I return resultArray.
        return resultArray;
    }
}

【问题讨论】:

  • 这不是深拷贝

标签: java methods parameters


【解决方案1】:

System.arraycopy 不做深拷贝;而是做一个浅拷贝。换句话说,它复制了引用,因此System.arraycopy(inpArray, 0, resultArray, 0, inpArray.length); 的行为如下:

inpArray[0] and resultArray[0] refer to the same object
inpArray[1] and resultArray[1] refer to the same object
inpArray[2] and resultArray[2] refer to the same object

等等……

这也意味着

inpArray[0] == resultArray[0] is true
inpArray[1] == resultArray[1] is true
inpArray[2] == resultArray[2] is true

等等……

【讨论】:

  • 感谢您的解释!
【解决方案2】:

变化:

//I copy in resultArray to keep unchanged inpArray.
int[][] resultArray = new int[inpArray.length][inpArray[0].length];
System.arraycopy(inpArray, 0, resultArray, 0, inpArray.length);

到:

// I copy in resultArray to keep unchanged inpArray.
int[][] resultArray = new int[inpArray.length][];
for (int i = 0; i < inpArray.length; i++) {
    resultArray[i] = new int[inpArray[i].length];

    for (int j = 0; j < resultArray[i].length; j++)
        resultArray[i][j] = inpArray[i][j];
}

除了您没有创建该区域的实际副本这一事实之外,您还将resultArray 的每个子数组设置为inpArray 中第一个元素的长度。大多数数组都会有不同长度的子数组,所以你应该给每个子数组一个单独的长度。

【讨论】:

  • 非常感谢。真的行。我正确理解我没有复制值,而是在执行arraycopy时将链接复制到嵌套的一维数组?
  • 是的,数组仍然由inpArray 的子数组组成。既然你提到了它,你应该可以用System.arraycopy替换第二个for循环。
猜你喜欢
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-18
相关资源
最近更新 更多