Skip to content
Go back

Is Java Pass-by-Reference or Pass-by-Value?

Published:  at  08:40 PM

If you’ve ever written code in Java—or even just talked about it with other developers—you’ve probably stumbled across this question: Is Java pass-by-reference or pass-by-value? It’s one of those topics that sparks endless debates in forums, classrooms, and coding interviews. And honestly? It can feel confusing at first. But don’t worry—I’m here to break it down for you in a way that’s easy to grasp, whether you’re a beginner or a seasoned programmer.

In this guide, we’ll explore what “pass-by-reference” and “pass-by-value” really mean, how Java handles them, and why it matters for your coding projects. With clear examples and a friendly explanation, you’ll walk away knowing exactly how Java works—and maybe even impress your friends with your newfound knowledge. Let’s get started!

Table of contents

Open Table of contents

What Does “Pass-by-Reference” and “Pass-by-Value” Mean?

Before we dive into Java, let’s get on the same page about what these terms mean. They’re all about how a programming language passes data (like variables) to functions or methods.

Pass-by-Value Explained

Imagine you’re handing someone a piece of paper with a number written on it—like “42.” They can read it, change it on their own paper, or throw it away, but your original paper stays the same. That’s pass-by-value. The function gets a copy of the data, not the original. So, any changes inside the function don’t affect what’s outside.

Pass-by-Reference Explained

Now picture this: instead of handing over a copy, you give someone the exact location of your paper—like “Check my desk, top drawer.” They can go there and change the number directly on your paper. That’s pass-by-reference. The function gets a direct link (or reference) to the original data, so changes inside the function affect the original too.

Got it? Great! Now let’s see how Java fits into this picture.


Is Java Pass-by-Reference or Pass-by-Value?

Here’s the short answer: Java is pass-by-value. Always. Every time. No exceptions. But here’s where it gets tricky—Java’s behavior with objects can feel like pass-by-reference, which is why people get confused. Let’s unpack this step-by-step.

Java and Primitive Types

Java has two kinds of data: primitive types (like int, double, char) and objects (like String, ArrayList, or custom classes). Let’s start with primitives, because they’re straightforward.

When you pass a primitive type to a method, Java makes a copy of the value and hands that copy over. The original stays untouched. Here’s an example:

public class Test {
    public static void main(String[] args) {
        int number = 10;
        System.out.println("Before: " + number);
        changeNumber(number);
        System.out.println("After: " + number);
    }

    public static void changeNumber(int x) {
        x = 20; // Changing the copy
    }
}

Output:

Before: 10
After: 10

What happened? The method changeNumber got a copy of 10 (called x). It changed x to 20, but the original number stayed 10. Classic pass-by-value!

Java and Objects

Now, let’s try this with an object, like a StringBuilder:

public class Test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        System.out.println("Before: " + sb);
        changeString(sb);
        System.out.println("After: " + sb);
    }

    public static void changeString(StringBuilder text) {
        text.append(" World"); // Adding to the object
    }
}

Output:

Before: Hello
After: Hello World

Wait a second—the original sb changed! Doesn’t that mean Java is pass-by-reference? Not quite. Here’s the key: Java still passed a copy—but it was a copy of the reference to the object, not the object itself.

The Big Reveal: It’s Pass-by-Value… of References!

In Java, objects live in a part of memory called the heap, and variables hold references (like addresses) to those objects. When you pass an object to a method, Java copies the reference and gives that copy to the method. Both the original and the copy point to the same object. So, if the method modifies the object (like adding “ World” to the StringBuilder), the change shows up everywhere.

But—and this is crucial—if the method tries to replace the object with something new, the original stays safe. Check this out:

public class Test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        System.out.println("Before: " + sb);
        replaceString(sb);
        System.out.println("After: " + sb);
    }

    public static void replaceString(StringBuilder text) {
        text = new StringBuilder("Goodbye"); // New object
    }
}

Output:

Before: Hello
After: Hello

Here, replaceString created a new StringBuilder and pointed text to it. But sb still points to the original “Hello” object. Why? Because only the copy of the reference changed, not the original reference. That’s pass-by-value in action!


Why Does This Confusion Happen?

The Java pass-by-reference or pass-by-value debate exists because objects make it feel like pass-by-reference. When you modify an object inside a method, it looks like the original changed directly. But the truth is, Java’s always copying something—either a primitive value or a reference. It never hands over the original “address” in a way that lets you swap it out completely.

Think of it like this:


How to Test This Yourself

Want to see it in action? Try these experiments:

Experiment 1: Swap Two Numbers

In a true pass-by-reference language (like C++), you could swap two variables in a method. Let’s try it in Java:

public class Test {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        System.out.println("Before: a = " + a + ", b = " + b);
        swap(a, b);
        System.out.println("After: a = " + a + ", b = " + b);
    }

    public static void swap(int x, int y) {
        int temp = x;
        x = y;
        y = temp;
    }
}

Output:

Before: a = 5, b = 10
After: a = 5, b = 10

No swap! Why? Java passed copies of a and b. The method swapped the copies, but the originals didn’t budge.

Experiment 2: Swap Objects

Now with objects:

public class Test {
    public static void main(String[] args) {
        Box box1 = new Box(5);
        Box box2 = new Box(10);
        System.out.println("Before: box1 = " + box1.value + ", box2 = " + box2.value);
        swap(box1, box2);
        System.out.println("After: box1 = " + box1.value + ", box2 = " + box2.value);
    }

    public static void swap(Box x, Box y) {
        Box temp = x;
        x = y;
        y = temp;
    }
}

class Box {
    int value;
    Box(int value) {
        this.value = value;
    }
}

Output:

Before: box1 = 5, box2 = 10
After: box1 = 5, box2 = 10

Again, no swap! The references were copied, and the method only swapped the copies, not the originals.


Table: Pass-by-Value vs. Pass-by-Reference

Here’s a quick comparison to clarify things:

FeaturePass-by-Value (Java)Pass-by-Reference
What’s PassedCopy of value or referenceDirect reference to original
Changes Affect Original?Only if object is modified, not replacedYes, always
Can Swap Variables?NoYes
ExamplesJava, C (primitives)C++, PHP (with &)

Why It Matters for Java Developers

Understanding Java pass-by-reference or pass-by-value isn’t just academic—it affects how you write code:


Conclusion: Java Is Pass-by-Value, Period

So, is Java pass-by-reference or pass-by-value? It’s pass-by-value—every time. Primitives get copied, and object references get copied too. The confusion comes from how object modifications look like pass-by-reference, but it’s all about passing a copy of the reference, not the original.

Next time you’re coding or debating with friends, you’ll have the answer ready. Want to dig deeper? Try the experiments above or play with more complex objects. Java’s got some quirks, but once you get this, you’re golden!


Resources



Next Post
Do You Have to Use (ASDF:load-system :xxxx) and (ql:quickload :yyyy) Every Time You Work in Lisp?