Understanding parameter passing in Java: Call By Value

Some of the first semester students participating in the lecture Algorithms and Datastructures where I am working as tutor seem to have problems understanding how parameter passing works in Java, so I decided to do a little writeup on this.

The most confusing part seems to be the passing of object references to methods, so I will mainly put the focus on this. But let us start with primitive parameters first.

In short terms Call By Value means a value is copied when it is passed to a method as a parameter. Whatever you do with this value within the method, it will not affect the passed in value from the outer scope. Here is a simple test program to clarify this behaviour:

public class CallByValuePrimitives {
    public static void main(String args[]){
        int a = 42;
 
        System.out.println("a before someMethod(a): " + a);
        someMethod(a); // a is copied and the copy is passed into the method
        System.out.println("a after someMethod(a): " + a);
    }
 
    public static void someMethod(int a){
        a = 23;
        System.out.println("a within someMethod(a) after changing it: " + a);
    }
}

This generates the following output:

a before someMethod(a): 42
a within someMethod(a) after changing it: 23
a after someMethod(a): 42

Now to the confusing part. What happens on passing a reference e.g. to an Array into a method ? Fairly easy, the same thing that happens with primitives. Their value is copied and passed into the method. But what is the value of an Array variable ? Have a look at the following line of Java code:

int a[] = new int[3];

People often think this means something like “I would like to have a variable named a. It should be able to contain three int values.” Well but what it really means is “Give me a variable a that is able to reference an int-Array. Next create a new int-Array of size three and make a referencing it.”. Another code snippet to clarify this:

public class ArrayVariableValue {
    public static void main(String args[]){
        int a[] = new int[3];
 
        a[0] = 42;
        a[1] = 23;
        a[2] = 66;
 
        System.out.println(a); // What would you expect here ?
    }
}

Output can be e.g:

[I@544a5ab2

Huh? Did you expect something like [42, 23, 66]? Well that is not the value of a. It's value is just a unique key to reference the Array containing the real data. Problems to imagine this? Perhaps a little picture could help.

Okay so far we learned that parameters passed to methods are copied and that an Array variable is just a reference to the associated data. The time has come to bring up the final confusion:

public class PassingAnArrayToAMethod {
    public static void main(String args[]){
        int a[] = new int[2];
        a[0] = 23;
        a[1] = 42;
 
        // Point 1
        printArray(a, "a in main before someMethod(a): ");
        someMethod(a);
        // Point 5
        printArray(a, "a in main after someMethod(a): ");
    }
 
    public static void someMethod(int[] a){
        // Point 2
        printArray(a, "a at the beginning of someMethod(a): ");
        a[0] = 42;
        // Point 3
        printArray(a, "a after changing a[0] to 42 in someMethod(a) : ");
        a = new int[5];
        // Point 4
        printArray(a, "a after assigning a new Array to it: ");
    }
 
    public static void printArray(int[] toPrint, String msg){
        System.out.println("Value of " + msg + toPrint);
        System.out.print("Array referenced by " + msg);
        System.out.print(" [");
        for(int i = 0; i < toPrint.length - 1; i++){
            System.out.print(toPrint[i] + ", ");
        }
        System.out.print(toPrint[toPrint.length - 1]);
        System.out.print("]");
        System.out.println();
        System.out.println();
    }
}

Output is:

Value of a in main before someMethod(a): [I@152b6651
Array referenced by a in main before someMethod(a):  [23, 42]

Value of a at the beginning of someMethod(a): [I@152b6651
Array referenced by a at the beginning of someMethod(a):  [23, 42]

Value of a after changing a[0] to 42 in someMethod(a) : [I@152b6651
Array referenced by a after changing a[0] to 42 in someMethod(a) :  [42, 42]

Value of a after assigning a new Array to it: [I@544a5ab2
Array referenced by a after assigning a new Array to it:  [0, 0, 0, 0, 0]

Value of a in main after someMethod(a): [I@152b6651
Array referenced by a in main after someMethod(a):  [42, 42]

At Point 1 we have the following situation:

Just an Array variable referencing an Array.

At Points 2, 3 and 4 the only visible a is the one passed in as parameter,  but I am drawing the one from the main method as well, to make clear that it still points to the same Array.

At Point 2 we have the following situation:

When passed to the method the value of main a is copied into the method a. They are both referencing the same Array.

At line 17 we changed the first element of the Array to 42. This directly affects the data within the Array, but not the references. The references just point to the Array containing the data. They don't know about it's contents.

As expected the output of the printArray(...) call at point 4 is [42,42]. After creating a new Array with five elements and assigning it to the method a at point 5 we have the following situation:

Note that we still have no access to the main a within the method, so there is no chance we are able to get a reference to the Array containing [42, 42] again. The method a points to the new Array which is filled with the default value 0 for an int-Array. Also note the value of the method a has changed to [I@544a5ab2.

At point 5 the processing of the method call has been finished and there is just the a from the main method left. It is still pointing to the same Array as before. The following picture illustrates this last situation.

Here is what you should keep in mind: Parameters for methods are copied and the method receives the copy as parameter. This applies to references as well. The reference itself is copied and passed in and not the object it is referencing. If you modify the referenced object it affects the outside world, if you just modify the reference passed in as parameter (e.g. by assigning another object) it has no effect on the outside world.

  • Shindeyogita003

    its so easy thanks

  • Shindeyogita003

    its so easy thanks