TIL: Java is Pass-by-Value

Taking it easy tonight so I wanted to spend time on more core Java fundamentals rather than get into anything too crazy. I came across a highly rated post on Stack Overflow related to the question of whether or not Java is pass by reference or pass by value. I remember that discussion coming up back when I was working through golang training, so I was curious to see what Java was.

Turns out that Java is completely pass by value! Was a big surprise to me. I assumed since we’re always talking about passing references that it would indeed be pass by reference.

Evidently that’s not the case. We will always be passing a value of some kind. For basic types, we’ll be passing the actual value. By for objects, we’ll be passing the value of the reference to the object in memory.

Then I found out that java does not have pointers, which thinking about it now makes sense if everything is a value.

To try to get this into my head a bit better, I went ahead and worked through a couple scenarios, as kindly detailed in this stack overflow post that show how passing the values works:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class NoOverride {

   public static void main(String[] args) {
       Dog2 aDog = new Dog2("Max");
       // we pass the object to foo
       foo(aDog);
       // aDog variable is still pointing to the "Max" dog when foo(...) returns
       System.out.println(aDog.getName().equals("Max")); // true
       System.out.println(aDog.getName().equals("Fifi")); // false
   }

   public static void foo(Dog2 d) {
       System.out.println(d.getName().equals("Max")); // true
       // change d inside of foo() to point to a new Dog instance "Fifi"
       d = new Dog2("Fifi");
       System.out.println(d.getName().equals("Fifi")); // true
   }
}

In this example, we see that we don’t actually override the existing value of aDog back in the main method. We’re creating a brand new object which has a completely different reference. So when we return back, the value of name on our aDog hasn’t been changed.

Compare that to the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class Override {

   public static void main(String[] args) {
       Dog2 aDog = new Dog2("Max");
       foo(aDog);
       System.out.println(aDog.getName().equals("Max")); // false
       System.out.println(aDog.getName().equals("Fifi")); // true
   }

   public static void foo(Dog2 d) {
       System.out.println(d.getName().equals("Max")); // true
       d.setName("Fifi");
       System.out.println(d.getName().equals("Fifi")); // true
   }
}

Because we’re setting the name on the reference that was passed in, which is aDog, when we return back from foo(), the name on aDog has been updated. We are no longer set to Max, but instead set to Fifi.

Still a little hard for me to conceptualize, but I think just knowing that EVERYTHING is pass-by-value makes it easier to digest. There are no pointers to worry about, only values.

💚