传递对Java方法的引用

传递对Java方法的引用,java,methods,reference,parameter-passing,Java,Methods,Reference,Parameter Passing,我一直在尝试解决一个需要几种方法的问题: 看起来很多,但是你不需要阅读这些方法。只需知道我正在将一个int[][]]传递给一个方法,在方法内部更改int[][],然后在方法外部检查是否等于int[][] public static boolean One(int[][] matrix){ matrix = transpose(matrix); matrix = reverseRow(matrix); return Arrays.deepEquals(matrix, cha

我一直在尝试解决一个需要几种方法的问题:

看起来很多,但是你不需要阅读这些方法。只需知道我正在将一个
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;    
}
方法一后的原件

0001
0001
0001
0001
这些变化发生在我运行转置(矩阵)和反转(矩阵)之后。请注意,在java调试模式下,当我跨过这些方法时,我可以看到原始代码被更改。我甚至没有提到原创。我修改了一个已通过版本的原始版本

因此,有3个问题:

  • 我认为传递给方法的对象不会被更改,除非您返回更改的对象,然后将原始对象设置为changed in main()或原始方法?我说的不是转置,也不是反转,因为它们应该在方法一中改变矩阵

  • 我用一个使用字符串的方法对此进行了测试。我的上述信念是正确的。int[][]是否不同

  • 我怎样才能修复它,使原来的不被改变?还是我错过了一些非常简单的东西


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

    正如前面的问题所讨论的,这些引用总是按值传递的

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

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

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

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

    2) 我用一个使用字符串的方法对此进行了测试。我的上述信念是正确的。int[][]是否不同

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

    字符串是一个不可变的对象。您可能试图通过分配给被调用方法的变量来更改调用方的变量

    3) 我怎样才能修复它,使原来的不被改变?还是我错过了一些非常简单的东西

    在将对数组的引用传递给方法之前,可以创建数组的副本

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


    本问题讨论了其他方法:。请注意,问题中接受的答案省略了创建二维数组的必要步骤。

    在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

    这使我们能够进行一些观察:

  • 基本类型(
    char
    int
    double
    等)不能在调用函数中更改,因为它们不包含任何方法来改变数据
  • 不可变对象(
    String
    Integer
    Double
    等)永远不能在函数中更改,因为根据定义,它们不包含改变数据的方法
  • 可变对象(
    StringBuilder
    BigInteger
    BigDecimal
    等)只能通过调用对象上的mutator方法(而不是通过重新分配变量)进行更改。对于数组,您可以将
    array[0]=newValue
    等视为
    数组上类似于
    list的mutator方法。为
    列表设置(0,newValue)

  • @MLPROGRAMER CiM您的意思是通过值传递。@MLPROGRAMER CiM这是Java,我们的变量包含值,这些值是对对象的引用。当我们将它们传递给方法时,会创建新的引用,这些引用是原始引用的副本。@MLProgrammer CiM,因此,当我们试图解释时,人们仍然感到困惑。@MLProgrammer CiM:正确的术语反映了正确的理解。说到这里:@MLProgrammer CiM-Pshemo不是学究。他正在传达一个对理解Java至关重要的想法,但经常被误解。这个想法对于理解这个问题很重要。如果你来自C++,那么考虑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
    }