Pass by Value: What a Method Really Receives
Brew Bar's happy-hour method lowers a drink's price, and it works. The "add a free cup" method changes the cup count, and it does nothing. Both look almost identical. The difference is one of the most asked questions about Java, and it has a single answer.
The rule
Java always passes a copy; for objects, the copy is a reference.
When you call a method, each parameter receives a copy of the value in the caller's variable. Java has no other mode.
- For a primitive such as
int, the value is the number itself. The method gets its own copy of the number, so changing it cannot affect the caller. - For an object or array, the value in the variable is a reference, an arrow to the object. The method gets a copy of the arrow, which points at the same object.
That gives two opposite results:
static void addFreeCup(int cups) {
cups++; // changes the method's copy only
}
static void happyHour(Drink d) {
d.priceCents -= 50; // follows the arrow: the shared object changes
}
static void swapForTea(Drink d) {
d = new Drink("Tea", 150); // re-points the method's copy of the arrow only
}int cups = 2;
addFreeCup(cups); // cups is still 2
Drink latte = new Drink("Latte", 300);
happyHour(latte); // latte.priceCents is now 250
swapForTea(latte); // latte is still the Latte, at 250People sometimes say "objects are passed by reference". That is not quite right, as swapForTea proves: if the caller's variable itself were passed, reassigning d would change latte. It does not.
String looks like an exception but is not. Strings are immutable, so a method cannot change the object, and s = s + "!" only re-points the method's own copy.
The shortcut
Inside the method, look at what happens to the parameter. Dot or index (d.price = ..., arr[0] = ...): you are changing the shared object, so the caller sees it. Plain = on the parameter (d = ..., cups = ...) or ++: you are changing the local copy, so the caller sees nothing.
Before the calls
latteholds an arrow to a Drink with priceCents 300.
Drills
Answer fast — trust the rule.
int cups = 2; addFreeCup(cups); System.out.println(cups); prints what?
A method static void clearFirst(int[] cupsSold) { cupsSold[0] = 0; } is called with an array whose first element is 40. What is that element afterwards?
Drink latte = new Drink("Latte", 300); swapForTea(latte); System.out.println(latte.name); prints what?
static void shout(String s) { s = s + "!"; } is called with name = "Asha". What is name afterwards?
Remember
- Java always passes a copy; for objects, the copy is a reference to the same object.
- Dot or index on a parameter changes the shared object; plain
=changes only the copy. - Trap: calling it "pass by reference" and expecting reassignment to reach the caller.
