Pass by Reference or Value?

Pass by Value

Java always passes arguments by value.

It’s simple in the case of primitives, a copy of the value is assigned to the function argument:

private void doSomething(int a) {
    a = a + 1;
    out.println(a);
}

private void myFunction() {
    int x = 5;
    doSomething(x);
    out.println(x);
}

As expected, this outputs:

6
5

The value of the x variable (5) is passed to the doSomething method and copied to an argument named a. This local argument is incremented by 1 and output. The result is 6.

When the function returns, we output the original x variable. Its value is still 5.

Similarly, when passing an object, a copy of the reference to the object is passed to the function:

private void doSomething(Car car) {
    car.setMake("BMW");
    car.setModel("SUV X1");

    car = new Car("Ford", "Exporer");
    out.println(car.getMake() + " " + car.getModel());    
}

private void myFunction() {
    var c = new Car("Mazda", "323");
    doSomething(c);
    out.println(c.getMake() + " " + c.getModel());
}

This outputs:

Ford Explorer
BMW SUV X1

In myFunction we have a variable named c which refers to a Car object in memory initialized to Mazda 323. We call c a reference because it is not the object, it points to the object. Its value is a reference to the object.

When the c variable is passed to the doSomething method, a copy of its value is passed – its value being a reference to the Car object.

The car argument of the doSomething method now points to the same Car object – Mazda 323.

Because the argument points to the same object, changes are applied directly to the object. So our Car object is now a BMW SUV X1.

Next. we change the car argument to refer to a newly created object (Ford Explorer). This change only affects the value of the car argument, the value of our c variable is untouched.

Lastly, we exit the function and our c variable is still pointing to the Car object it had created, the Mazda 323 which had been updated to a BMW SUV X1.

Pass by Reference

In languages like C#, it is possible to actually pass our original variable by reference (var), or a reference to an uninitialized variable (out). This is useful in some circumstances, and you’ll see idioms like:

public bool TryParse(String text, out int result) { 
    // ... 
}

int x;

if (TryParse("123", out x)) { ... }

This function will try convert the string to an integer, if successful the referenced variable result is initialized with the integer value and true is returned. On failure, false is returned. With modern C# this idiom is even more concise.

Not to worry, in Java we can achieve a similar idiom using Optional:

public Optional<Integer> TryParse(String text) {
  // try convert and set result

  return success ? Optional.of(result) : Optional.empty();
}

int x = TryParse("123");

if (x.isPresent()) { .... }

Remember, Java always passes by value.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s