将引用传递给方法Java

时间:2015-08-07 23:16:17

标签: java methods reference parameter-passing

我一直试图解决需要两种方法的问题:

它看起来很多,但你真的不需要阅读这些方法。只知道我将int[][]传递给方法,更改方法内的int[][],然后检查方法外的int[][]是否相等。

public static boolean One(int[][] matrix){
    matrix = transpose(matrix);
    matrix = reverseRow(matrix);
    return Arrays.deepEquals(matrix, changed);
}
public static boolean Two(int[][] matrix){
    //180 degree clockwise
    matrix = transpose(matrix);
    matrix = reverseRow(matrix);
    matrix = transpose(matrix);
    matrix = reverseRow(matrix);
    return Arrays.deepEquals(matrix,changed);
}
public static int[][] transpose(int[][] matrix){
    for(int i = 0; i < N; i++) {
          for(int j = i+1; j < N; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
          }
        }
    return matrix;
}
public static int[][] reverseRow(int[][] matrix){
    for(int j = 0; j < N; j++){
        for(int i = 0; i < N / 2; i++) {
            int temp = matrix[j][i];
            matrix[j][i] = matrix[j][N - i - 1];
            matrix[j][N - i - 1] = temp;
        }
    }
    return matrix;
}
public static int[][] reverseCol(int[][] matrix){
    for(int col = 0;col < matrix[0].length; col++){
        for(int row = 0; row < matrix.length/2; row++) {
            int temp = matrix[row][col];
            matrix[row][col] = matrix[matrix.length - row - 1][col];
            matrix[matrix.length - row - 1][col] = temp;
        }
    }
    return matrix;    
}

问题的结构如下:    我有原始数字的int [] []    我有一个int [] []数字,这是原始数字转换的结果。具体而言,顺时针旋转90度,顺时针旋转180度。

实际问题要大得多,但我认为不存在直接解决问题的规则,所以我将其缩减到我需要的地方。

问题在于:    在运行方法一之后,原始数组会被修改,所以在我运行方法二之前它已经被破坏了。

例如, 方法一之前的原文:

1111
0000
0000
0000

原创方法之一;

0001
0001
0001
0001

这些变化发生在我运行转置(矩阵)和reverseRow(矩阵)之后。请注意,在java调试模式下,当我跳过这些方法时,我可以看到原始文件被更改。我想知道原来的意思。我修改了传递的原始版本的传递。

所以,3个问题:

  1. 我认为传递给方法的对象不会被更改,除非您返回更改的对象,然后将原始设置为main()或原始方法中的更改?我不是在谈论转置或者反向,因为那些应该改变方法一中的矩阵。

  2. 我用一个使用字符串的方法对此进行了测试。我上面的信念是正确的。 int [] []有什么不同吗?

  3. 如何修复它以便原始版本不会被更改?或者我错过了一些非常简单的东西?

2 个答案:

答案 0 :(得分:3)

当您了解到Java变量包含引用而不是对象时,这是最容易理解的。

这些引用总是按值传递,如前面的问题Is Java "pass-by-reference" or "pass-by-value"?中所讨论的那样。

这个答案解决了您的具体问题。

  

1)我认为传递给方法的对象不会被更改,除非您返回更改的对象,然后将原始设置为main()或原始方法中的更改?

对象不会传递给方法。 Java变量是对象的引用。您可以复制java变量而无需复制对象。

如果将引用类型的变量传递给方法,则该方法无法修改变量。但是,它可以修改变量引用的对象,如果它是可变的。

  

2)我用一个使用字符串的方法测试了这个。我上面的信念是正确的。 int [] []有什么不同吗?

数组是您通过引用访问的可变对象。

String是一个不可变对象。你可能试图通过分配被调用方法的变量来改变调用者的变量。

  

3)如何修复它以便原件不会被更改?或者我错过了一些非常简单的事情?

您可以在将对数组的引用传递给方法之前复制该数组。

一维数组的一种方法是使用System.arraycopy()。您的二维数组是由多个一维数组构成的,因此您可以使用多个System.arraycopy()调用来复制它。

此问题讨论了其他方法:How do I copy a 2 Dimensional array in Java?。请注意,问题中接受的答案省略了创建二维数组的必要步骤。

答案 1 :(得分:0)

在Java中,所有内容都通过传递。然而,令人困惑的是,该值为原始对象保留了引用

分配变量只会改变输入变量的引用:

void doSomething(String str){
    str = "New String"; // str variable now holds a reference to "New String"
                        // however, the original String Object was not changed
}

但是,不会更改原始字符串。事实上,String是一个不可变的对象,以及所有原语int,double等。这引出了以下声明:

更改调用函数的输入参数的唯一方法是调用该参数的方法来改变对象(例如param.setValue(newValue)param[0] = newValue)。

这使我们能够做出一些观察:

  1. 原始类型(charintdouble等)永远不能在调用函数中更改,因为它们不包含任何改变数据的方法。
  2. 不可变对象(StringIntegerDouble等)永远不能在函数中更改,因为根据定义它们不包含改变数据的方法。
  3. 可变对象(StringBuilderBigIntegerBigDecimal等)只能通过调用对象上的mutator方法来更改(而不是通过重新分配变量)。对于数组,您可以将array[0] = newValue等视为Array的mutator方法,类似于list.set(0, newValue)的{​​{1}}。