Java course menu
Java Parameters and Return Values: Pass by Value Explained
Understand how Java passes arguments: always by value, what that means for primitives versus object references, why a method can change an object's contents but not the caller's variable, varargs, and returning several values with a record.
On this page
"Is Java pass by value or pass by reference?" is one of the most common Java interview questions. The precise answer: Java is always pass by value. But for objects, the value that is copied is a reference, which explains behaviour that surprises many beginners.
Primitives: the method gets a copy#
public class Main {
static void addBonus(int salary) {
salary += 5000;
System.out.println("Inside: " + salary);
}
public static void main(String[] args) {
int salary = 50000;
addBonus(salary);
System.out.println("Outside: " + salary);
}
}Inside: 55000
Outside: 50000The parameter is a separate variable holding a copy of the value. Changing it has no effect on the caller. To get a changed value back, return it:
public class Main {
static int withBonus(int salary) {
return salary + 5000;
}
public static void main(String[] args) {
int salary = 50000;
salary = withBonus(salary);
System.out.println(salary);
}
}55000Objects: a copy of the reference#
A variable of an object type (an array, a list, your own class) holds a reference to the object. Passing it copies the reference, so the method and the caller refer to the same object. The method can therefore change the object's contents:
import java.util.ArrayList;
import java.util.List;
public class Main {
static void addItem(List<String> cart, String item) {
cart.add(item);
}
static void doubleAll(int[] values) {
for (int i = 0; i < values.length; i++) {
values[i] *= 2;
}
}
public static void main(String[] args) {
List<String> cart = new ArrayList<>();
addItem(cart, "Milk");
addItem(cart, "Bread");
System.out.println(cart);
int[] numbers = {1, 2, 3};
doubleAll(numbers);
System.out.println(numbers[0] + " " + numbers[1] + " " + numbers[2]);
}
}[Milk, Bread]
2 4 6But a method cannot replace the caller's object#
Assigning a new object to the parameter only changes the method's copy of the reference. The caller's variable still points to the original:
import java.util.ArrayList;
import java.util.List;
public class Main {
static void replace(List<String> cart) {
cart = new ArrayList<>(); // only the local copy now points to a new list
cart.add("Something new");
}
public static void main(String[] args) {
List<String> cart = new ArrayList<>(List.of("Milk"));
replace(cart);
System.out.println(cart);
}
}[Milk]That is why a classic swap(a, b) method cannot work in Java: the method can only swap its own copies.
Strings are immutable#
String methods never change the string; they return a new one. So a method cannot change a caller's string through its parameter, and must return the result:
public class Main {
static String shout(String text) {
return text.toUpperCase() + "!";
}
public static void main(String[] args) {
String message = "hello";
String loud = shout(message);
System.out.println(message + " / " + loud);
}
}hello / HELLO!Varargs: any number of arguments#
Type... name lets a method accept any number of arguments, which arrive as an array:
public class Main {
static double average(double... numbers) {
if (numbers.length == 0) return 0;
double sum = 0;
for (double n : numbers) sum += n;
return sum / numbers.length;
}
public static void main(String[] args) {
System.out.println(average(4, 8, 6));
System.out.println(average(10));
System.out.println(average());
}
}6.0
10.0
0.0The varargs parameter must be the last parameter. String.format and List.of use varargs.
Returning several values#
A method returns one value, but that value can be an object holding several parts. A record (Java 16+) is the neatest way to define one; see Records and Enums:
public class Main {
record MinMax(int min, int max) {}
static MinMax minMax(int[] values) {
int lo = values[0];
int hi = values[0];
for (int v : values) {
lo = Math.min(lo, v);
hi = Math.max(hi, v);
}
return new MinMax(lo, hi);
}
public static void main(String[] args) {
MinMax result = minMax(new int[] {12, 7, 21, 9});
System.out.println(result.min() + " " + result.max());
System.out.println(result);
}
}7 21
MinMax[min=7, max=21]Common mistakes#
Practice#
Practice exercise
Write void applyDiscount(double[] prices, double percent) that reduces every price in the array by the given percentage, and test it with {850, 1200, 99.5} and 10%.
Show solution
import java.util.Arrays;
public class Discounts {
static void applyDiscount(double[] prices, double percent) {
for (int i = 0; i < prices.length; i++) {
prices[i] -= prices[i] * percent / 100;
}
}
public static void main(String[] args) {
double[] prices = {850, 1200, 99.5};
applyDiscount(prices, 10);
System.out.println(Arrays.toString(prices));
}
}[765.0, 1080.0, 89.55]The method changes the caller's array because both refer to the same array object. Arrays.toString formats an array for printing.
Key takeaway#
Finished this lesson?