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
xandy?
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 receives | A copy of the argument’s value | An alias for the caller’s variable itself |
| Assigning to the parameter | Changes only the copy | Changes the caller’s variable |
Can swap(a, b) swap the caller’s variables? | No | Yes |
| Languages | Java (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 = 10Java 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 = 20The 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:
Balance: 1500 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: 1000If Java were pass by reference,myAccountwould now be the new object with 99999. It isn’t, becauseaccwas 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’smyAccountstill points to A. Whenreplacereturns, 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? trueThe 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 -> 1000Every 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!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: 41Integer 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 = 35000The 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| Need | Do this |
|---|---|
A new primitive or String value | Return it: salary = withBonus(salary); |
| Several values | Return a record (Java 16+) or a small object |
| A new object | Return it from a factory method |
| Change an existing object’s state | Pass 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]
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 it | Caller unaffected | Caller unaffected | Caller 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
- Remember one sentence: Java copies the value; for objects, the value is a reference.
- Return new values instead of trying to change the caller’s variables.
- Make it obvious when a method mutates an argument (
addGraceMarks(marks)), and avoid hidden mutation in “get” or “print” methods. - Make defensive copies of arrays and collections you must not change.
- Prefer immutable types (
String, records) for values that shouldn’t change, so sharing a reference is always safe. - 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
- 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.
- 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.
- Why does
Stringlook like it’s passed by value butStringBuilderdoesn’t? Both are passed the same way;Stringis immutable andStringBuilderis mutable. - Does
finalon a parameter change passing semantics? No. It only blocks reassignment inside the method. - 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
- Easy: Write
static void tryToReset(int n)that setsn = 0, and print the caller’s value before and after. - Easy: Write
static void fill(int[] arr, int value)that sets every element, and show that the caller sees the change. - Easy–Medium: Write
static void rename(StringBuilder name)andstatic void rename(String name), and explain why only one changes the caller. - Medium: Write a working “swap” for two
intvariables using a returned record. - 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.
StringandIntegerlook “unchangeable” because they’re immutable, not because they’re passed differently;finaldoesn’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