How do Java objects are passed - by reference or by value ?

on waitingforcode.com

How do Java objects are passed - by reference or by value ?

You're still doing Java/C#/JavaScript/Python/PHP... and need a wind of change? I was like that 4 years ago. I changed then to the data engineering field and it solved my existential problems :) If you want to follow my path, I prepared a course that will help you with that! Join the class!
Understanding if given object is passed by value or by reference is important to write efficient programs. Which is the strategy in Java ?

The post explains if Java objects are passed by value or by reference. The first part compares both methods. The second part shows, through some examples and schema, how objects are passed in Java.

Pass by value vs pass by reference

Before talking directly about passing objects in Java, let's try to explain what are these 2 different methods of moving objects between functions in programming. The first method is called pass by value. Simply speaking, passed objects are the copies. If we take an PHP example:

function incrementByValue($number, $incrementationValue) {
  $number = $number + $incrementationValue;
}

$i = 0;
incrementByValue($i, 5);
echo "Incremented by value: ".$i." \n"; 

Printed value will be 5 ? Obviously not. It will be still 0. It's because $number variable is passed by value, so it's copied to the incrementByValue method. If we printed $number inside this method, we'd see that it's correctly incremented to 5. In the other side, below code will do the job and print 5 in the last statement:

function incrementByReference(&$number, $incrementationValue) {
  $number = $number + $incrementationValue; 
}

$i = 0;
incrementByReference($i, 15);
echo "Incremented by reference: ".$i." \n";

Printed value will be 5, as expected. It's because we use a special PHP's instruction &$var which means a stuff like "do not copy variable $var but take the reference of it directly". More purely speaking, instead of copied object, the reference or alias of it is passed to the method.

Passing objects in Java

In Java objects are always passed by value and never ever by reference. Does it mean that each object is copied, as in the case of PHP example from the previous part ? No, it doesn't. The clearest way to think about it is to precise that object references are passed by value and not objects themselves.

Wait a minute, what these object references are ? Java is often considered as more secure language than C++ because it doesn't allow, among others, pointer arithmetic ("a play with memory addresses"). Since we can't operate on memory addresses directly, Java needs other representation of them. And this representation is brought by object references. They're used to describe the pointer to the memory location of given object. Because they're more secure, they only supports assignment operations - we can only let one reference to point to another object.

To be more clear, please consider following 2 images:

1

2

In the first image we pass the value of object reference to a Car object. changeCarName(...) method uses this reference to create a local variable called changedCar that points to Car#Reference1. The invocation of changedCar.setName(...) operates on the same reference, so, on the same object. In the other side, the second image shows the creation of new Car object. This new object points, through local method variable oldCar to Car#Reference2. But myCar variable, defined in upper level, doesn't change and still points to Car#Reference1.

To be even more clear, we can explain that as Gevorg did on Stackoverflow:

  • The 1st image
    1. A variable myCar and object Car are created. myCar references created Car.
    2. It passes myCar object reference in changeCarName method.
    3. changeCarName(...) initializes local variable changedCar pointing to the same object reference
  • The 2nd image
    1. A variable myCar and object Car are created. myCar references created Car.
    2. It passes myCar object reference in buyNewCar method.
    3. buyNewCar(...) initializes local variable oldCar pointing to the same object reference
    4. After in buyNewCar(...) we create new Car object and, subsequently, new object reference held by oldCar.

Java pass by value example

Below you can find some learning tests proving that in Java we pass object references by value:

@Test
public void should_prove_that_java_is_passing_by_value() {
  Car myCar = new Car("My car");
  int originalHashCode = myCar.hashCode();

  // buyNewCar(...) creates new Car object, and new object reference.
  // But myCar should still point to its original object reference.
  buyNewCar(myCar);

  assertThat(myCar.name).isEqualTo("My car");
  assertThat(myCar.hashCode()).isEqualTo(originalHashCode);
}

@Test
public void should_call_mutator_method_and_impact_original_object() {
  Car myCar = new Car("My car");
  int originalHashCode = myCar.hashCode();

  // changeCarName(...) changes the name of Car defined as method's argument.
  // Thus, this argument points to the same object reference as myCar.
  // The changes are made on one physical Car object
  changeCarName(myCar);

  assertThat(myCar.name).isEqualTo("new_My car");
  assertThat(myCar.hashCode()).isEqualTo(originalHashCode);
}

@Test
public void should_add_entry_to_list() {
  List<String> letters = new ArrayList<>();

  // letters from addLetter(...) signature points to the same
  // object reference than letters from caller
  // We expect that adding new letters impacts caller's object
  addLetter(letters, "A");

  assertThat(letters).hasSize(1);
  assertThat(letters.get(0)).isEqualTo("A");
}

private static void addLetter(List<String> letters, String letter) {
  letters.add(letter);
}

private static void changeCarName(Car car) {
  car.name = "new_"+car.name;
}

private static void buyNewCar(Car oldCar) {
  oldCar = new Car("My new car");
}

private static class Car {
  private String name;

  public Car(String name) {
      this.name = name;
  }
}

This post explains how Java passes objects to methods. As we can see, it passes them by values of object references. Even if it sound similar to "pass by reference", both terms can't be used interchangeably. In all cases, Java passes object (references) by value.

Share on: