Pass by Value in Java: Is Java Pass by Value or Pass by Reference?

Difficulty: Beginner–Intermediate · Importance: High · Java version: All versions (one example uses a record, Java 16+) · Last updated: 1 Nov 2026

Interview puzzle: Does this swap x and y?

It prints x = 10, y = 20. Nothing swapped. The reason is one rule, and this lesson shows how far it reaches.

Quick Answer

Java is always pass by value. When you call a method, Java copies each argument’s value into the parameter. For primitives (int, double…), the number itself is copied. For objects and arrays, the value copied is the reference, so the method can change the object’s contents, but it can never make the caller’s variable point to a different object.

Before you start: this builds on Method Parameters, where you first saw that a parameter gets a copy of the argument.

What Do Pass by Value and Pass by Reference Mean?

Pass by value (call by value)Pass by reference (call by reference)
What the method receivesA copy of the argument’s valueAn alias for the caller’s variable itself
Assigning to the parameterChanges only the copyChanges the caller’s variable
Can swap(a, b) swap the caller’s variables?NoYes
LanguagesJava (always), C, Python-style “call by sharing”C++ (int &a), C# (ref)

Analogy: pass by value is giving a friend a photocopy of your notes; they can scribble on it, and your original is untouched. Pass by reference is handing over your actual notebook.

To see real pass by reference, here is C++, where & makes the parameters aliases:

Output (g++ 13.3):

 C++ after swap: x = 20, y = 10

Java has no equivalent of &. There’s no way to declare a parameter that aliases the caller’s variable.

Primitive Types: The Value Is Copied

Output:

Inside swap: a = 20, b = 10After swap:  x = 10, y = 20

▶ Try it in the ExamAdda Compiler

The swap did happen, but only to a and b, which are copies living in swap’s own stack frame. When swap returns, the frame and the copies disappear.

What the Bytecode Shows

For a method that changes a double parameter (applyDiscount(price) sets price = price * 0.8), javap -c on JDK 25 shows:

 public static void main(java.lang.String[]);         0: ldc2_w        #25     // double 500.0d
3: dstore_1 // main's local slot 1 = 500.0
4: dload_1 // push a COPY of slot 1
5: invokestatic #27 // Method applyDiscount:(D)V

static void applyDiscount(double);
0: dload_0 // applyDiscount's OWN slot 0
1: ldc2_w #7 // double 0.8d
4: dmul
5: dstore_0 // overwrites only its own slot 0

main keeps price in its slot 1. The call pushes a copy, which becomes applyDiscount’s slot 0. dstore_0 writes to the callee’s slot, and there’s no instruction that could reach back into main’s slot 1. Running it prints Inside method: 400.0 then In main: 500.0.

Reference Types: The Reference Is Copied

A variable of an object type doesn’t hold the object; it holds a reference to an object on the heap. Passing it copies that reference. Now two variables point to the same object.

Output:

This is the result that makes people say “objects are passed by reference”. They aren’t. Watch what happens when the method reassigns its parameter:

Output:

Inside replace: 99999In main:        1000

If Java were pass by reference, myAccount would now be the new object with 99999. It isn’t, because acc was only a copy of the reference.


Both frames start pointing at Account A. acc = new Account() redirects only the method’s copy to Account B; main’s myAccount still points to A. When replace returns, B is unreachable and eligible for garbage collection.

Proof With ==

== on references checks whether two variables point to the same object:

parameter now == original? falsemethod received the original object? true

The method received a reference to the same object (true). Reassigning its parameter didn’t touch the caller’s variable.

One rule explains everything: the method gets a copy of the variable’s value. For objects that value is a reference. Changing the object through it is visible to the caller; changing the copy itself is not. Some people call this “call by sharing”, but in Java’s terms it is pass by value.

Order Matters: Mutate, Then Reassign

Output:

mutateThenReassign -> 2000reassignThenMutate -> 1000

▶ Try it in the ExamAdda Compiler

Every change made before reassignment goes to the shared object. Everything after goes to the new one. That’s a favourite trick question.

Arrays Follow the Same Rule

Arrays are objects, so a method can change their elements. That’s how you can swap in Java: swap positions inside an array.

Output:

 [1, 3, 2]

Reassigning the array parameter (values = new int[3]) would not affect the caller, exactly like Account. Arrays are covered fully next, in Introduction to Arrays.

Are Strings Passed by Reference in Java?

No. Strings follow the same rule; they just look different because String is immutable: no method can change a String object. Compare with the mutable StringBuilder:

Output:

String:        puneStringBuilder: pune!

▶ Try it in the ExamAdda Compiler

With String, the only “changes” a method can make are creating new strings and reassigning its local copy, and neither reaches the caller. StringBuilder can be mutated through the shared reference. Same passing rule, different object type. You’ll learn why String is immutable in the Strings section.

Integer and Other Wrapper Objects

Output:

Inside increment: 42In main:          41

Integer objects are immutable too. count++ unboxes, adds 1, boxes a new Integer, and reassigns the local count. The caller still points to 41. Wrapper parameters behave just like primitives here.

Does final Make a Parameter Pass by Reference?

No. final only stops the method from reassigning its own copy; it doesn’t freeze the object or change how passing works:

Output:

 [75, 80]

How to Get Changes Back to the Caller

Since a method can’t rebind the caller’s variable, return the new value and let the caller assign it:

Output:

x = 20, y = 10salary = 35000

▶ Try it in the ExamAdda Compiler

The same applies to “creating” an object inside a method. Passing in null and assigning new Account() to the parameter leaves the caller’s variable null:

Output:

After createAccount: nullAfter newAccount: balance 100
NeedDo this
A new primitive or String valueReturn it: salary = withBonus(salary);
Several valuesReturn a record (Java 16+) or a small object
A new objectReturn it from a factory method
Change an existing object’s statePass the object and mutate it (and document that you do)

See also Method Return Types.

Real-World Bug: A Method That Quietly Changes Your Data

Because array and object references are shared, a method can unexpectedly modify the caller’s data:

Output:

Top price: 1299Cart order now: [99, 249, 499, 1299]
Top price: 1299
Cart order now: [499, 99, 1299, 249]

▶ Try it in the ExamAdda Compiler

A method that only reads data sorted the shopping cart in place, so the “order added” was lost. A defensive copy (Arrays.copyOf) fixes it. The rule: methods that aren’t meant to modify an input should work on a copy.

Pass by Value vs Pass by Reference: What Can a Java Method Do?

Inside the method…Primitive (int)Immutable object (String, Integer)Mutable object / array (int[], StringBuilder, Account)
Change the parameter’s value / reassign itCaller unaffectedCaller unaffectedCaller unaffected
Change the object’s contents—Impossible (immutable)Caller sees it
Swap the caller’s two variables❌ Never❌ Never❌ Never (you can swap elements inside one array)

Common Mistakes

Mistake 1: Writing swap(a, b) and Expecting It to Work


Mistake 2: Saying “Objects Are Passed by Reference”

The method can change the object, but reassigning the parameter never affects the caller (ObjectReassign prints 1000). The precise phrase is: object references are passed by value.

Mistake 3: Expecting a Method to Change a String or Integer

shout(city) and increment(visits) leave the caller’s values unchanged. Fix: return the new value: city = city.toUpperCase();.

Mistake 4: “Returning” a Result by Assigning to the Parameter

createAccount(a) leaves a as null. Fix: return the new object.

Mistake 5: Unintentionally Modifying the Caller’s Data

printTopPrice sorted the caller’s array. Fix: copy before modifying (Arrays.copyOf, and later List.copyOf).

Mistake 6: Thinking final Means “Can’t Be Changed”

final int[] marks still lets the method change marks[0]. final only blocks reassignment of the local parameter.

Best Practices

  1. Remember one sentence: Java copies the value; for objects, the value is a reference.
  2. Return new values instead of trying to change the caller’s variables.
  3. Make it obvious when a method mutates an argument (addGraceMarks(marks)), and avoid hidden mutation in “get” or “print” methods.
  4. Make defensive copies of arrays and collections you must not change.
  5. Prefer immutable types (String, records) for values that shouldn’t change, so sharing a reference is always safe.
  6. Don’t reassign parameters at all; it confuses readers about what the caller sees.

Interview Questions on Pass by Value

How to answer in an interview: “Is Java pass by value or pass by reference?”
“Java is always pass by value. For primitives, the method gets a copy of the value. For objects and arrays, the variable holds a reference, and that reference is copied. So the method can modify the object’s state through it, but if it reassigns the parameter to a new object, the caller’s variable is unaffected. That’s why a swap method can’t swap two variables in Java.”

Output-Prediction Questions

Q1.

Answer: 9. The first write hits the shared array; after reassignment, a points elsewhere.

Q2.

Answer: Hello. Only the local copy was reassigned.

Q3.

Answer: HelloWorld. The append happened before reassignment.

Conceptual Follow-Ups

  1. Why can’t we write a swap method for two ints in Java? The method gets copies; it can’t reach the caller’s variables.
  2. Is an array passed by reference? No. The array’s reference is passed by value; its elements can be changed, but the array can’t be replaced.
  3. Why does String look like it’s passed by value but StringBuilder doesn’t? Both are passed the same way; String is immutable and StringBuilder is mutable.
  4. Does final on a parameter change passing semantics? No. It only blocks reassignment inside the method.
  5. Which languages support true pass by reference? C++ (&) and C# (ref), for example. Java doesn’t.

More: Java Interview Questions for Freshers · Intermediate Questions · Scenario-Based Questions

Practice Exercises

  1. Easy: Write static void tryToReset(int n) that sets n = 0, and print the caller’s value before and after.
  2. Easy: Write static void fill(int[] arr, int value) that sets every element, and show that the caller sees the change.
  3. Easy–Medium: Write static void rename(StringBuilder name) and static void rename(String name), and explain why only one changes the caller.
  4. Medium: Write a working “swap” for two int variables using a returned record.
  5. Medium: Write static int secondHighest(int[] marks) that doesn’t change the caller’s array (hint: copy, then sort).

Practise on ExamAdda Practice and test in the ExamAdda Compiler.

FAQs

1. Is Java pass by value or pass by reference?
Java is always pass by value. For objects, the value being copied is the reference, so methods can change an object’s contents but can’t make the caller’s variable point to a different object.

2. Why does changing an object inside a method affect the caller?
Because the caller’s variable and the parameter hold copies of the same reference, both pointing to one object on the heap. Changing that object is visible through either reference.

3. Why doesn’t a swap method work in Java?
The method receives copies of the two values (or references) and swaps only those copies. The caller’s variables are never touched.

4. Are arrays passed by reference in Java?
No. The array’s reference is passed by value. The method can change elements, which the caller sees, but reassigning the array parameter doesn’t affect the caller.

5. Are strings passed by reference in Java?
No. Strings are passed by value like everything else. Because String is immutable, a method can’t change the caller’s string at all; it can only create new strings.

6. What is call by value and call by reference?
Call by value passes a copy of the argument; call by reference passes an alias to the caller’s variable. Java supports only call by value.

7. How do I return multiple changed values from a Java method?
Return an object that holds them, such as a record (Java 16+) or an array, and assign the results in the caller.

Article Summary

  • Java is always pass by value: each parameter receives a copy of the argument’s value.
  • For objects and arrays, the copied value is a reference, so the object’s contents can change but the caller’s variable can’t be redirected.
  • Mutations made before reassigning a parameter reach the shared object; anything after reassignment doesn’t.
  • String and Integer look “unchangeable” because they’re immutable, not because they’re passed differently; final doesn’t change passing either.
  • To change a caller’s values, return them; to protect a caller’s data, make defensive copies.

Next → Introduction to Arrays in Java · ← Previous: Recursion in Java

References: JLS §15.12.4.5: Create Frame, Synchronize, Transfer Control · JLS §4.3.1: Objects (reference values) · Oracle Java Tutorials: Passing Information to a Method