Статья

Java: передача параметров по значению или по ссылке?

Термины “передача по значению” и “передача по ссылке” имеют особые, точные определения в программировании. Эти термины отличаются от интуиции, которая возникает у многих людей, когда они впервые слышат данные определения.

В терминах “передача по значению” и “передача по ссылке” говорится о переменных. Передача по значению указывает, что функции или методу передается значение переменной. Передача по ссылке обозначает, что функции или методу передается ссылка на переменную (или косвенный адрес переменной в памяти), это дает возможность изменять содержимое переменной.

Если исходить из этих определений, то в Java переменные всегда передаются по значению. К сожалению, когда мы имеем дело с переменными, содержащими объекты, мы на самом деле имеем дело с дескрипторами объектов, называемыми ссылками, которые также передаются по значению. Эта терминология и семантика легко сбивают с толку многих новичков.

Рассмотрим пример:
public static void main(String[] args) {
    Cat aCat = new Cat("Max");
    Cat oldCat = aCat;

    // передаем объект в функцию foo

    foo(aCat);

    // переменная aCat все еще будет указывать на кота "Max", после вызова foo()

    aCat.getName().equals("Max"); 
    // true

    aCat.getName().equals("Nick"); 
    // false

    aCat == oldCat; 
    // true

}

public static void foo(Cat d) {
    d.getName().equals("Max"); 
    // true

    // меняем d внутри foo(), d будет ссылаться на новый экземпляр Cat с именем "Nick"

    d = new Cat("Nick");
    d.getName().equals("Nick"); 
    // true

}
В приведенном выше примере aCat.getName() все равно вернет строку “Max”. Значение aCat внутри main не изменяется в функции foo, поскольку ссылка на объект передается по значению. Если сам объект был бы передан по ссылке, то вызов метода aCat.getName() в main вернул бы строку “Nick” после вызова foo.

В C++, C, Pascal и других языках, поддерживающих прямую передачу по ссылке, вы действительно можете изменить переданную переменную, в отличии от Java.

В Java аргументы примитивных типов (int, long и т.д.) по умолчанию передаются по значению, а объекты по умолчанию передаются по значению ссылки на объект.
java