Короткий ответ
Java — строго pass-by-value. При вызове метода создаётся копия значения аргумента. Для примитивных типов копируется само значение, для ссылочных — копия ссылки на тот же объект. Поэтому изменения состояния объекта внутри метода видны снаружи, а переприсваивание параметра — нет.
Как это работает подробнее
Разница между передачей по ссылке (как в C++) и по значению проявляется в двух типовых сценариях.
- Примитивный аргумент. Изменение параметра внутри метода никак не влияет на переменную в вызывающем коде: метод работает с копией значения.
- Ссылочный аргумент. По значению передаётся копия ссылки, но объект тот же самый: вызов
list.add(...)или изменение поля будет видно снаружи. - Переприсваивание. Если внутри метода выполнить
param = new Something(), изменится только локальная копия ссылки, а исходная переменная продолжит указывать на прежний объект.
Пример кода
PassByValue.java
import java.util.*;
public class PassByValue {
static void change(int x) {
x = 10;
}
static void addItem(List<String> list) {
list.add("new");
}
public static void main(String[] args) {
int a = 1;
change(a);
System.out.println(a); // 1 — примитив не изменился
List<String> list = new ArrayList<>();
addItem(list);
System.out.println(list.size()); // 1 — объект изменился
}
}Что использовать на практике
- Помнить, что классический «обмен значений двух переменных» через метод в Java не работает — меняются лишь копии.
- Когда нужно вернуть изменённое значение, возвращать его из метода, а не переприсваивать параметр.
- Для изменения внешнего состояния использовать мутацию переданного объекта.