简体   繁体   中英

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.

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. Specifically, a 90 degree clockwise turn, and an 180 degree clockwise turn.

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). Note that in java debug mode, I can see original being changed when I step over these methods. I DIDN'T EVEN MENTION ORIGINAL. I modified a passed of a passed version of Original.

So, 3 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? I'm not talking about transpose, or reverseRow, because those were supposed to change matrix inside method One.

  2. I tested this out with a method using strings. My belief above held true. Are int[][]'s different?

  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.

And those references are always passed by value, as discussed in the earlier question Is Java "pass-by-reference" or "pass-by-value"? .

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?

Objects don't get passed to methods. Java variables are references to objects. You can copy a java variable without copying the object.

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. My belief above held true. Are int[][]'s different?

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? 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() . Your two dimensional array is constructed from multiple one-dimensional arrays, so you could use multiple calls to System.arraycopy() to copy it.

Other approaches are discussed in this question: How do I copy a 2 Dimensional array in 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 . 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:

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 ).

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.
  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.
  3. Mutable Objects ( StringBuilder , BigInteger , BigDecimal , etc.) can only change by calling mutator methods on the object (not by reassigning the variable). 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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