Java: pass-by-reference or pass-by-value? Full analysis

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: the eternal battle "by reference" vs "by value"



If you've ever written in Java and passed an array or object to a method, and then wondered why the original data changed — you are not alone. This question has plagued beginners (and not only) since the language's inception. On Stack Overflow, it has garnered millions of views, and debates in the comments have raged for years.



Today, we will settle this once and for all: Is Java "pass-by-reference" or "pass-by-value"? Spoiler: the answer is unambiguous, but the devil, as always, is in the details. We won't just give a dry definition; we will show with real examples how argument passing works in Java, and why many people get confused.



What do the creators of Java say?



The official documentation and James Gosling himself (the creator of Java) leave no room for debate: Java always passes arguments by value (pass-by-value). No exceptions. Neither for primitives nor for objects.



But then why does code change objects? Why does a List or array passed to a method get modified? Let's figure it out.



Pass-by-value: what does it actually mean?



First, a clear definition. Pass-by-value means that when a method is called, a copy of the variable's value is created, and it is this copy that is passed to the method. The original variable (in the calling code) remains untouched.



Pass-by-reference is when a reference to the original variable is passed to the method, and the method can directly change its value (for example, replace the object). This does not exist in Java.



Now — to the examples.



Example 1: primitive types (int, double, boolean)



With primitives, everything is obvious. Let's write some simple code:



public class Main {    public static void main(String[] args) {        int x = 10;        changePrimitive(x);        System.out.println("After method x = " + x); // 10    }

public static void changePrimitive(int value) { value = 20; // changing the copy }}


Output:

After method x = 10


It all makes sense: we passed a copy of the number 10, changed the copy to 20 inside the method, but the original remained as it was. This is pure pass-by-value.



Example 2: objects (strings, lists, custom classes)



And now for the interesting part. Look:



public class Main {    public static void main(String[] args) {        StringBuilder sb = new StringBuilder("Hello");        changeStringBuilder(sb);        System.out.println("After method: " + sb); // Hello World!    }

public static void changeStringBuilder(StringBuilder builder) { builder.append(" World!"); // changing the object's content }}


Output:

After method: Hello World!


"Aha! — you might say. — The object changed! So this is pass-by-reference!"



No. This is the trap that 90% of beginners fall into. Let's break down what actually happened.



What is stored in the variable sb?



In Java, a variable of an object type (e.g., StringBuilder, List, String) does not store the object itself. It stores a reference (address) to the object in memory. The object itself resides somewhere in the heap.



When you pass sb to a method, you pass a copy of this reference. That is, a copy of the address. Both the original and the copy point to the same object. Therefore, when you change the object's content through the copy of the reference, these changes are also visible through the original reference.



But! If you try to assign a new object to the parameter inside the method, the original reference will not change. Let's prove it:



public class Main {    public static void main(String[] args) {        StringBuilder sb = new StringBuilder("Hello");        changeReference(sb);        S                

Blogs

Book Recommendations