简体   繁体   English

传递对方法Java的引用

[英]Passing References to Methods Java

I've been trying to solve a problem that requires a couple of methods: 我一直在尝试解决需要两种方法的问题:

IT LOOKS LIKE A LOT, but you don't really need to read the methods. 它看起来很像,但您实际上并不需要阅读这些方法。 Just know that I'm passing an int[][] to a method, changing the int[][] inside the method, then checking for equality to an int[][] outside the method. 只是知道我正在将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;    
}

The structure of the problem is as follows: I have an int[][] of original numbers I have an int[][] of numbers, that is a result of a transformation of the original numbers. 问题的结构如下:我有原始数字的int [] []我有数字的int [] [],这是原始数字转换的结果。 Specifically, a 90 degree clockwise turn, and an 180 degree clockwise turn. 具体而言,顺时针旋转90度,顺时针旋转180度。

The actual problem is much bigger, but I think there's a rule against getting straight up answers to problems, so I cut it down to what I need. 实际问题要大得多,但是我认为有一个规则不能直接获得问题的答案,因此我将其缩减为我所需要的。

The problem is this: After I run method one, the original array becomes modified, so it's corrupted before I run method two. 问题是这样的:运行方法一后,原始数组被修改,因此在运行方法二之前它已损坏。

For instance, Original before method One: 例如,方法一之前的原始:

1111
0000
0000
0000

Original after method One; 方法一之后的原稿;

0001
0001
0001
0001

These changes happens right after I run transpose(matrix) and reverseRow(matrix). 这些变化发生在我运行transpose(matrix)和reverseRow(matrix)之后。 Note that in java debug mode, I can see original being changed when I step over these methods. 请注意,在Java调试模式下,当我跳过这些方法时,可以看到原始内容已更改。 I DIDN'T EVEN MENTION ORIGINAL. 我什至没有提到原来的。 I modified a passed of a passed version of Original. 我修改了原始版本的通过版本。

So, 3 questions: 因此,有3个问题:

  1. I thought that objects passed to methods don't get changed unless you return the changed object and then set the original to the changed in main() or the original method? 我以为传递给方法的对象不会被更改,除非您返回更改的对象,然后在main()或原始方法中将原始对象设置为更改的对象? I'm not talking about transpose, or reverseRow, because those were supposed to change matrix inside method One. 我不是在谈论transpose或reverseRow,因为这些应该在方法One中更改矩阵。

  2. I tested this out with a method using strings. 我使用一种使用字符串的方法对此进行了测试。 My belief above held true. 我的上述信念是正确的。 Are int[][]'s different? int [] []不同吗?

  3. How can I fix it so that original doesn't get changed? 我该如何解决它,使原件不变? Or am I missing something really simple? 还是我错过了一些非常简单的事情?

This is easiest to understand when you learn that Java variables hold references, not objects. 当您了解Java变量保存引用而不是对象时,这最容易理解。

And those references are always passed by value, as discussed in the earlier question Is Java "pass-by-reference" or "pass-by-value"? 而且这些引用始终按值传递,如前面的问题中所述, Java是“按引用传递”还是“按值传递”? .

This answer addresses your specific questions. 该答案解决了您的特定问题。

1) I thought that objects passed to methods don't get changed unless you return the changed object and then set the original to the changed in main() or the original method? 1)我认为传递给方法的对象不会被更改,除非您返回更改的对象,然后将原始对象设置为main()或原始方法中更改的对象?

Objects don't get passed to methods. 对象不会传递给方法。 Java variables are references to objects. Java变量是对对象的引用 You can copy a java variable without copying the object. 您可以复制Java变量而不复制对象。

If you pass a variable of reference type to a method, that method can't modify your variable. 如果将引用类型的变量传递给方法,则该方法无法修改您的变量。 It can, however, modify the object referenced by the variable, if it's mutable. 但是,如果它是可变的,它可以修改变量引用的对象。

2)I tested this out with a method using strings. 2)我测试了使用字符串的方法。 My belief above held true. 我的上述信念是正确的。 Are int[][]'s different? int [] []不同吗?

The array is a mutable object that you're accessing through a reference. 数组是您要通过引用访问的可变对象。

The String is an immutable object. 字符串是一个不可变的对象。 You're probably trying to change the caller's variable by assigning to the called method's variable. 您可能正在尝试通过分配给被调用方法的变量来更改调用者的变量。

3)How can I fix it so that original doesn't get changed? 3)如何修复它,使原件不被更改? Or am I missing something really simple? 还是我错过了一些非常简单的事情?

You can make a copy of the array before passing a reference to it to a method. 您可以在将数组的引用传递给方法之前制作该数组的副本。

One way to do that for a one-dimensional array is to use System.arraycopy() . 对一维数组执行此操作的一种方法是使用System.arraycopy() Your two dimensional array is constructed from multiple one-dimensional arrays, so you could use multiple calls to System.arraycopy() to copy it. 您的二维数组是由多个一维数组构成的,因此您可以使用对System.arraycopy()多次调用来复制它。

Other approaches are discussed in this question: How do I copy a 2 Dimensional array in Java? 此问题讨论了其他方法: 如何在Java中复制二维数组? . Note that the accepted answer in the question omits the necessary step of creating the two-dimensional array. 请注意,问题中接受的答案省略了创建二维数组的必要步骤。

In Java everything is passed by value . 在Java中,一切都是通过传递的。 However, the confusing thing is that this value holds a reference to the original object. 但是,令人困惑的是,该值保留了原始对象的引用

Assigning a variable only changes what reference the input variable holds: 分配变量只会更改输入变量的引用:

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

However, this does not change the original string. 但是,这不会更改原始字符串。 In fact, String is an immutable Object, along with all primitives int, double, etc. This leads me to the following statement: 实际上,String和所有原语int,double等都是一个不可变的对象。这使我得出以下语句:

The only way to change an input parameter of a calling function is to call a method of that parameter that mutates the object (eg param.setValue(newValue) or param[0] = newValue ). 更改调用函数的输入参数的唯一方法是调用该参数使对象发生突变的方法(例如param.setValue(newValue)param[0] = newValue )。

This allows us to make a couple observations: 这使我们可以进行一些观察:

  1. Primitive types ( char , int , double , etc.) can never be changed in a calling function because they don't contain any methods to mutate the data. 原始类型( charintdouble等)不能在调用函数中进行更改,因为它们不包含任何使数据变异的方法。
  2. Immutable Objects ( String , Integer , Double , etc.) can never be changed in a function, because by definition they do not contain methods that mutate the data. 不可变对象( StringIntegerDouble等)永远不能在函数中更改,因为根据定义,它们不包含使数据可变的方法。
  3. Mutable Objects ( StringBuilder , BigInteger , BigDecimal , etc.) can only change by calling mutator methods on the object (not by reassigning the variable). 可变对象( StringBuilderBigIntegerBigDecimal等)只能通过在对象上调用mutator方法来更改(而不能通过重新分配变量来更改)。 For arrays, you can think of array[0] = newValue , etc., as mutator methods on an Array akin to list.set(0, newValue) for a List . 对于数组,你能想到的array[0] = newValue等作为上mutator方法Array类似于list.set(0, newValue)用于一个List

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM