Термины “передача по значению” и “передача по ссылке” имеют особые, точные определения в программировании. Эти термины отличаются от интуиции, которая возникает у многих людей, когда они впервые слышат данные определения.
В терминах “передача по значению” и “передача по ссылке” говорится о переменных. Передача по значению указывает, что функции или методу передается значение переменной. Передача по ссылке обозначает, что функции или методу передается ссылка на переменную (или косвенный адрес переменной в памяти), это дает возможность изменять содержимое переменной.
Если исходить из этих определений, то в 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 и т.д.) по умолчанию передаются по значению, а объекты по умолчанию передаются по значению ссылки на объект.
В C++, C, Pascal и других языках, поддерживающих прямую передачу по ссылке, вы действительно можете изменить переданную переменную, в отличии от Java.
В Java аргументы примитивных типов (int, long и т.д.) по умолчанию передаются по значению, а объекты по умолчанию передаются по значению ссылки на объект.