Параметры в Java передаются по ссылке или по значению?
Этот вопрос уходит корнями в C++ прошлое (скорее всего интервьюера), это терминология из C++. Для начала нужно разобраться в этой терминологии.
В C++ ссылка – это переменная-псевдоним для другой переменной. Меняя значение ссылки, поменяется и оригинал. В Java такого нет, легко понять это подумав например о ссылке на int.
Ссылка в Java – это нечто похожее на адрес объекта в памяти. Похожая сущность в C++ называется указатель.
Передача параметра по значению – это копирование значения в переменную-параметр метода. По ссылке – передача ссылки, то есть по сути использование той же самой переменной. Разобраться подробнее (осторожно, много C++).
В Java параметр метода – всегда копия. Значит параметры передаются всегда по значению, просто это значение может быть ссылкой на объект. Код ниже это демонстрирует.
Объекты передаются по ссылке или нет?
Часто можно услышать фразу, что в PHP «объекты всегда передаются по ссылке». На самом деле всё немного сложнее.
Как выглядит работа с ссылками в PHP? Для этого используется специальный синтаксис – перед именем переменной или параметра функции ставится символ амперсанда (&). В том случае, когда амперсанд проставлен в сигнатуре функции – это называют передачей параметра по ссылке. Изменяя такую переменную-параметр внутри функции, после выхода из функции мы обнаружим, что значение поменялось и в месте вызова. Думаю, с этим знакомы все.
А что с объектами? Объекты, переданные внутрь какой-то функции в качестве аргументов, ведут себя точно также – если внутри функции мы меняем внутреннее состояние объекта, то снаружи увидим это изменённое состояние. Отличие в том, что в сигнатуре функции не нужно ставить амперсанд перед параметром-объектом.

Отсюда можно сделать ошибочный вывод, что объекты всегда передаются по ссылке, просто синтаксис попроще, не надо обмазываться амперсандами.
А что, если в сигнатуре функции, принимающей объект всё-таки поставить амперсанд? После небольшой проверки, на первый взгляд, ничего не поменяется! Кажется очередной фрактал плохого дизайна: скалярные типы данных можно передать двумя способами, и по ссылке, и по значению, а объекты всегда по ссылке, при этом амперсанд хочешь ставь, хочешь не ставь.
На самом деле, это заблуждение. Разберёмся что здесь происходит.
Упрощённо, механику можно представить так: когда мы создаём объект с помощью оператора new и присваиваем какой-то переменной, в эту переменную помещается не сам объект, а некий идентификатор объекта, id.
Передавая переменную в качестве аргумента внутрь какой-то функции, мы передаём значение этого идентификатора, т.е. передача происходит по значению . Важно понимать, что значением является не сам объект, а его идентификатор.
Таким образом снаружи функции и внутри мы, имея одинаковое значение идентификатора объекта, работаем с одним и тем же объектом.
Но если внутри функции мы присвоим переменной, например null – повлияет ли это на объект снаружи функции? Никак! Мы обнулили переменную содержащую id объекта внутри функции, но снаружи функции, внешняя переменная всё ещё содержит id объекта и сам объект никуда не делся из памяти.
Теперь ставим в сигнатуре функции амперсанд. В этом случае переменная, содержащая идентификатор объекта, передастся по ссылке. Поменяв такую переменную внутри функции, например, присвоив null , мы обнаружим что поменялась и переменная снаружи – она тоже стала null . А объект в памяти стал ничьим и он будет удалён сборщиком мусора.
Подводим итог.
- Формулировка «объекты всегда передаются по ссылке» не корректна. Впрочем, с практической точки зрения такое упрощение не приводит к проблемам в общении с другими разработчиками, все воспринимают эту фразу примерно одинаково: изменив состояние объекта внутри функции мы увидим это и снаружи.
- Есть существенная разница между синтаксисом с амперсандом и без него. Но на практике не припомню, чтобы мне требовалось использовать вариант с амперсандом перед переменной-объектом.
JavaScript: передача по значению или по ссылке?

Часто возникает путаница в понимании, как JavaScript передает аргументы в функции — по значению или по ссылке. Для начала, сгенерируем пример:
let a = 1; let b = a; b++; console.log(a); // Вывод: 1 console.log(b); // Вывод: 2
В этом примере, переменная b получает значение переменной a , затем это значение изменяется, но исходное значение переменной a при этом не меняется. Это подтверждает, что примитивные типы данных в JavaScript передаются по значению.
Теперь рассмотрим случай с объектами:
let obj1 = < prop: 1 >; let obj2 = obj1; obj2.prop++; console.log(obj1.prop); // Вывод: 2 console.log(obj2.prop); // Вывод: 2
Здесь, на первый взгляд, кажется, что объекты передаются по ссылке, так как изменение свойства объекта obj2 приводит к изменению свойства исходного объекта obj1 .
Однако, это не совсем так. В JavaScript все данные передаются по значению. В случае с объектами, значение — это ссылка на объект. Поэтому, когда мы присваиваем obj2 = obj1 , мы копируем значение ссылки на объект, а не сам объект. В результате обе переменные указывают на один и тот же объект в памяти, и изменение свойств этого объекта через одну переменную влияет на его отображение через другую переменную.
Подводя итог, можно сказать, что JavaScript является языком с передачей данных по значению. Однако в случае с объектами, это значение представляет собой ссылку на объект.
Как передаются переменные по значению или по ссылке
Строки, числа, логические значения передаются в функцию по значению . Иными словами при передаче значения в функцию, эта функция получает копию данного значения. Рассмотрим, что это значит в практическом плане:
function change(x) < x = 2 * x; console.log("x in change:", x); >let n = 10; console.log("n before change:", n); // n before change: 10 change(n); // x in change: 20 console.log("n after change:", n); // n after change: 10
Функция change получает некоторое число и увеличивает его в два раза. При вызове функции change ей передается число n. Однако после вызова функции мы видим, что число n не изменилось, хотя в самой функции произошло увеличение значения параметра. Потому что при вызове функция change получает копию значения переменной n. И любые изменения с этой копией никак не затрагивают саму переменную n. В итоге мы получим следующий вывод в консоли браузера
n before change: 10 x in change: 20 n after change: 10
Передача по ссылке
Объекты и массивы представляют ссылочные типы. То есть переменная или константы, которая представляет объект или массив, по сути хранит ссылку или иными словами указатель, которые указывают на адрес в памяти, где хранится объект. Например:
let bob =< name: "Bob" >;
Переменная bob формально хранит объект, в котором определено одно поле name. Фактически же переменная bob хранит ссылку на объект, который расположен где-то в памяти.
И ссылочные типы — объекты и массивы передаются в функцию по ссылке . То есть функция получает копию ссылки на объект, а не копию самого объекта.
function change(user) < user.name = "Tom"; >let bob =< name: "Bob" >; console.log("before change:", bob.name); // Bob change(bob); console.log("after change:", bob.name); // Tom
В данном случае функция change получает некоторый объект и меняет его свойство name. При вызове этой функции в нее передается значение переменной bob:
change(bob);
Но поскольку переменная bob представляет объект и хранит ссылку на некоторый объект в памяти, то функция change получае копию этой ссылки, которая указывает на тот же объект в памяти, что и переменная bob.
В итоге мы увидим, что после вызова функции изменился оригинальный объект bob, который передавался в функцию.
before change: Bob after change: Tom
Однако если мы попробуем переустановить объект или массив полностью, оригинальное значение не изменится.
function change(user)< // полная переустановка объекта user= < name:"Tom" >; > let bob =< name: "Bob" >; console.log("before change:", bob.name); // Bob change(bob); console.log("after change:", bob.name); // Bob
Почему здесь данные не изменяются? Потому что, как писалось выше, функция получает копию ссылки . То есть при передачи в функцию параметру user значения переменной bob:
change(bob);
Переменная bob и параметр user представляют две разные ссылки, но которые указывают на один и тот же объект.
При присвоении параметру в функции другого объекта:
user= < name:"Tom" >;
ссылка user начиначет указывать на другой объект в памяти. То есть после этого bob и user — две разные ссылки, которые указывают на два разных объекта в памяти.
То же самое касается массивов:
function change(array) < array[0] = 8; >function changeFull(array) < array = [9, 8, 7]; >let numbers = [1, 2, 3]; console.log("before change:", numbers); // [1, 2, 3] change(numbers); console.log("after change:", numbers); // [8, 2, 3] changeFull(numbers); console.log("after changeFull:", numbers); // [8, 2, 3]