Weirdness in Equated Java Arrays: References vs. Pointers

后端 未结 4 1519
囚心锁ツ
囚心锁ツ 2020-12-11 21:48

Having a problem understanding what\'s going on n the code below. The behavior of arrays c and d is what I would expect. But what\'s going on with

相关标签:
4条回答
  • 2020-12-11 21:54

    There is nothing "weird" going on here: array variables are references to the actual arrays (also known as pointers in other languages). When you manipulate array variables, all you do is manipulating pointers.

    When you assign an array variable to another one, you create an alias to the array pointed to by the variable you assign, and make the array previously pointed to by the variable being assigned eligible for garbage collection. Because the assignment a = b makes a an alias of b, filling b with data acts exactly the same as filling a with data: once the assignment is complete, a and b are merely two different names for the same thing.

    As far as pass by value is concerned, none of it is going on in your example: the concept of passing by value applies only when you pass objects as parameters to the methods that you call. In your example, variables a, b, c, and d are not method parameters, they are local variables. You do pass them by reference to methods toString and fill (or more precisely, you pass by value the references to your objects to toString and fill, because in Java everything is passed by value), that is why modifications to your arrays done by fill are visible upon the return from the method.

    0 讨论(0)
  • 2020-12-11 22:00

    There is an important point of arrays that is often not taught or missed in java classes. When arrays are passed to a function, then another pointer is created to the same array ( the same pointer is never passed ). You can manipulate the array using both the pointers, but once you assign the second pointer to a new array in the called method and return back by void to calling function, then the original pointer still remains unchanged.

    You can directly run the code here : https://www.compilejava.net/

    import java.util.Arrays;
    
    public class HelloWorld
    {
        public static void main(String[] args)
        {
            int Main_Array[] = {20,19,18,4,16,15,14,4,12,11,9};
            Demo1.Demo1(Main_Array);
            // THE POINTER Main_Array IS NOT PASSED TO Demo1
            // A DIFFERENT POINTER TO THE SAME LOCATION OF Main_Array IS PASSED TO Demo1
    
            System.out.println("Main_Array = "+Arrays.toString(Main_Array));
            // outputs : Main_Array = [20, 19, 18, 4, 16, 15, 14, 4, 12, 11, 9]
            // Since Main_Array points to the original location,
            // I cannot access the results of Demo1 , Demo2 when they are void.
            // I can use array clone method in Demo1 to get the required result,
            // but it would be faster if Demo1 returned the result to main
        }
    }
    
    public class Demo1
    {
        public static void Demo1(int A[])
        {
            int B[] = new int[A.length];
            System.out.println("B = "+Arrays.toString(B)); // output : B = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            Demo2.Demo2(A,B);
            System.out.println("B = "+Arrays.toString(B)); // output : B = [9999, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            System.out.println("A = "+Arrays.toString(A)); // output : A = [20, 19, 18, 4, 16, 15, 14, 4, 12, 11, 9]
    
            A = B;
            // A was pointing to location of Main_Array, now it points to location of B
            // Main_Array pointer still keeps pointing to the original location in void main
    
            System.out.println("A = "+Arrays.toString(A)); // output : A = [9999, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            // Hence to access this result from main, I have to return it to main
        }
    }
    public class Demo2
    {
        public static void Demo2(int AAA[],int BBB[])
        {
            BBB[0] = 9999;
            // BBB points to the same location as B in Demo1, so whatever I do
            // with BBB, I am manipulating the location. Since B points to the
            // same location, I can access the results from B
        }
    }
    
    0 讨论(0)
  • 2020-12-11 22:04

    The array initializer is calling new under the hood (so in this case it's syntactic saccharine). Your swap nearer the top is just swapping references, the one below is performing exactly how you'd expect a reference to perform.

    The linked article refers to parameters... In Java all parameters are by value, it's just that references themselves get passed by value i.e. changes to the REFERENCE (not its dereferenced content) won't be reflected outside the scope of the subroutine.

    0 讨论(0)
  • 2020-12-11 22:17

    When you make an assignment like a = b;, if a and b are not primitives, then they now reference the same object. In your case, they now reference the same array. Any change you make to either one will also affect the other (because you're only updating one thing, and both a and b are pointing at it).

    Note that this behavior is unrelated to how parameters are passed in Java.

    0 讨论(0)
提交回复
热议问题