Categories
java methods parameter-passing pass-by-reference pass-by-value

Is Java “pass-by-reference” or “pass-by-value”?

7475

I always thought Java uses pass-by-reference.

However, I’ve seen a blog post that claims that Java uses pass-by-value.

I don’t think I understand the distinction they’re making.

What is the explanation?

11

  • 5

    We would more commonly say that a variable “passed-by-reference” can be mutated. The term appears in textbooks because language theorists needed a way to distinguish how you treat primitive data types (int, bool, byte) from complex and structured objects (array, streams, class) — that is to say, those of possibly unbounded memory allocation.

    – jlau

    Aug 4, 2020 at 11:35

  • 4

    I want to note that you do not have to think about this in most cases. I programmed java for many years until i learned c++. Until this point in time i had no clue what pass-by-reference and pass-by-value are. The intuitive solution always worked for me, which is why java is one of the best languages for beginners. So if you currently are worried, if your function needs a reference or a value, just pass it as it is and you will be fine.

    – Tobias

    Oct 20, 2020 at 11:44

  • 52

    Java pass the reference by value.

    Oct 20, 2020 at 19:05

  • 14

    Putting it very concisely, this confusion arises because in Java all non-primitive data types are handled/accessed by references. However, passing is always be value. So for all non-primitive types reference is passed by its value. All primitive types are also passed by value.

    Nov 10, 2020 at 6:56

  • 5

    I found this quite helpful: baeldung.com/java-pass-by-value-or-pass-by-reference

    Jan 20, 2021 at 9:52

3470

I just noticed you referenced my article.

The Java Spec says that everything in Java is pass-by-value. There is no such thing as “pass-by-reference” in Java.

The key to understanding this is that something like

Dog myDog;

is not a Dog; it’s actually a pointer to a Dog. The use of the term “reference” in Java is very misleading and is what causes most of the confusion here. What they call “references” act/feel more like what we’d call “pointers” in most other languages.

What that means, is when you have

Dog myDog = new Dog("Rover");
foo(myDog);

you’re essentially passing the address of the created Dog object to the foo method.

(I say essentially because Java pointers/references aren’t direct addresses, but it’s easiest to think of them that way.)

Suppose the Dog object resides at memory address 42. This means we pass 42 to the method.

if the Method were defined as

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

let’s look at what’s happening.

  • the parameter someDog is set to the value 42
  • at line “AAA”
    • someDog is followed to the Dog it points to (the Dog object at address 42)
    • that Dog (the one at address 42) is asked to change his name to Max
  • at line “BBB”
    • a new Dog is created. Let’s say he’s at address 74
    • we assign the parameter someDog to 74
  • at line “CCC”
    • someDog is followed to the Dog it points to (the Dog object at address 74)
    • that Dog (the one at address 74) is asked to change his name to Rowlf
  • then, we return

Now let’s think about what happens outside the method:

Did myDog change?

There’s the key.

Keeping in mind that myDog is a pointer, and not an actual Dog, the answer is NO. myDog still has the value 42; it’s still pointing to the original Dog (but note that because of line “AAA”, its name is now “Max” – still the same Dog; myDog‘s value has not changed.)

It’s perfectly valid to follow an address and change what’s at the end of it; that does not change the variable, however.

Java works exactly like C. You can assign a pointer, pass the pointer to a method, follow the pointer in the method and change the data that was pointed to. However, the caller will not see any changes you make to where that pointer points. (In a language with pass-by-reference semantics, the method function can change the pointer and the caller will see that change.)

In C++, Ada, Pascal and other languages that support pass-by-reference, you can actually change the variable that was passed.

If Java had pass-by-reference semantics, the foo method we defined above would have changed where myDog was pointing when it assigned someDog on line BBB.

Think of reference parameters as being aliases for the variable passed in. When that alias is assigned, so is the variable that was passed in.

28

  • Minor clarification question on the above example, so when creating new Dog at BBB at address 72, does this imply upon return the created Dog at 72 and it’s value is lost and reverts back to 42?

    – ebresie

    Mar 13, 2021 at 14:40

  • 3

    @ebresie javarevisited.blogspot.com/2015/09/….

    Mar 15, 2021 at 17:08


  • 1

    @NiharGht Good point – I’ve clarified it (please comment again if it’s still not clear)

    Jun 10, 2021 at 7:03

  • 1

    Java does not act exactly like C. If you pass a pointer to a function in C and modify where that pointer points to, the effect of reassigning that pointer is seen at the call sight, not just within the scope of the call. Seeking this behavior out of the languages is the purpose of the const keyword. Please stop saying java is just like C, because it’s in many many fundamental ways entirely NOT c (or c++) and all you’re doing is confusing people that do know C (or C++) and are trying to get a working overview of java. See: courses.washington.edu/css342/zander/css332/passby.html

    – Jonathan

    Jun 24, 2021 at 17:20

  • 2

    @Jonathan That link is C++, not C. C does not work that way. C is strictly pass by value, just like Java. If you pass a pointer to something, the pointer is the value that you can follow. You cannot change the pointer but can follow it and change the value it points to. If you re-point it, the caller does not see the change. In C++, you can pass a reference to something (seen in that page you reference as int&), which is similar to an alias; if you change it in a function/method it does actually change the object/primitive/pointer passed as an argument.

    Jun 26, 2021 at 20:14

2049

Java always passes arguments by value, NOT by reference.


Let me explain this through an example:

public class Main {

     public static void main(String[] args) {
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will modify the object that the reference variable "f" refers to!
     }

     public static void changeReference(Foo a) {
          Foo b = new Foo("b");
          a = b;
     }

     public static void modifyReference(Foo c) {
          c.setAttribute("c");
     }

}

I will explain this in steps:

  1. Declaring a reference named f of type Foo and assign it a new object of type Foo with an attribute "f".

    Foo f = new Foo("f");
    

    enter image description here

  2. From the method side, a reference of type Foo with a name a is declared and it’s initially assigned null.

    public static void changeReference(Foo a)
    

    enter image description here

  3. As you call the method changeReference, the reference a will be assigned the object which is passed as an argument.

    changeReference(f);
    

    enter image description here

  4. Declaring a reference named b of type Foo and assign it a new object of type Foo with an attribute "b".

    Foo b = new Foo("b");
    

    enter image description here

  5. a = b makes a new assignment to the reference a, not f, of the object whose attribute is "b".

    enter image description here

  6. As you call modifyReference(Foo c) method, a reference c is created and assigned the object with attribute "f".

    enter image description here

  7. c.setAttribute("c"); will change the attribute of the object that reference c points to it, and it’s the same object that reference f points to it.

    enter image description here

I hope you understand now how passing objects as arguments works in Java 🙂

2

  • 54

    Java always passes arguments by value, but what you are passing by value is a reference to an object, not a copy of the object. Simple eh?

    Dec 7, 2020 at 8:48

  • “Object not by Reference”, really?

    Dec 4, 2021 at 12:47