Переменная в Java — это контейнер, со значением в нем. Так что значит «передать» переменную? И какова разница между примитивными и ссылочными типами данных.
Мы доберемся до этого позже. Давайте сначала начнем с простого присваивания. Что делает данный код:
int х = 3;
int у = х;
В строке 1 создается переменная x типа int и ей присваивается значение 3.
В строке 2, создается переменная y типа int и ей присвается значение переменной x.
В дальнейшем переменная x никак не влияет на y. Java копирует значение х (3) и помещает эту копию в у.
Это передача параметра по значению. Вы не записываете одну переменную в другую. Значение копируется и присваивается новой переменной.
Выражение у = х; НЕ означает "записать x в y". Оно означает "скопировать значение внутри х и записать эту копию в у".
Если позже я изменю y:
у = 34;
Повлияет ли это на x? Конечно нет. x по прежнему имеет значение 3.
Если позже я изменю х:
х = 90;
Как это отразится на y? Никак. Они никак не связаны после того, как было сделано присвоение (КОПИРОВАНИЕ значения).
А что насчет ссылочных типов? Как они работают?
Не так уж сложно, на самом деле это правило то же самое. Ссылки делают тоже самое - вы получаете копию ссылки.
Так что, если я говорю:
Cat A = new Cat ();
Cat B = A;
Ссылка А копируется в ссылку B. К объекту это не относится — у вас по прежнему всего один объект.
Но теперь у вас есть две различных ссылки, контролирующие один и тот же объект Cat.
Теперь давайте рассмотрим передачу параметров в методы.
Java передает параметры по значению. Всегда.
Это означает — "скопировать значение и передать копию."
Для примитивных типов это легко:
int х = 5;
doStuff (х); / / Передать копию х (значение 5) в метод doStuff
Метод doStuff выглядит следующим образом:
void doStuff (int у) {
/ / Действия с 'y'
}
Копия значения x, тоесть 5, передается в метод doStuff ().
Метод doStuff () имеет свою собственную переменную, которая называется y.
Переменная y — новая, другая переменная. С копией того, что было в х на момент передачи его в метод. С этого момента, у и х не влияют друг на друга. При изменении у, вы не затрагиваете х.
void doStuff (int у) {
у = 27; / / Это не влияет на 'х'
}
И наоборот — при изменении х, вы не измените y. Единственное что сделал x в этом деле это скопировал свое значение и передал его в метод doStuff().
Как "передача по значению" работает со ссылками?
Слишком многие люди говорят, "Java передает примитивные типы по значению, а объекты по ссылке". Это не так как говорят. Java передает все по значению. С примитивами, вы получаете копию содержимого. Со ссылками вы тоже получаете копию содержимого.
Но что такое содержимое ссылки?
Пульт дистанционного управления. Средства для управления / доступа к объекту.
Когда вы передаете ссылку на объект в метод, вы передаете копию ссылки. Клон пульта дистанционного управления. Объект все еще сидит в куче где был создан, ожидая кого-то, чтобы использовали пульт. Объект не волнует сколько пультов "запрограммированы" чтобы контролировать его. Это волнует только сборщика мусора и вас, программиста.
Поэтому, когда вы говорите:
Cat A = new Cat ();
doStuff (А);
void doStuff (Cat B) {
/ / Использование B
}
Существует только один объект Cat. Но теперь два пульта управления (ссылки) могут получить доступ к одному и тому же объекту Cat.
Так что теперь все, что B делает объекту Cat, повлияет на Cat, на который указывает A, но это не повлияет на содержимое A!
Вы можете изменить Cat, используя новую ссылку B (скопированную непосредственно с А), но вы не можете изменить А.
Какого черта это значит?
Вы можете изменить объект, на который ссылается А, но вы не можете взять и изменить ссылку А — переадресовать её на другой объект или null. Так что если вы измените ссылку B (не сам объект Cat на который ссылается B, а само значение ссылки) вы не измените значение А. И наоборот.
Так что:
Cat A = new Cat ();
doStuff (А);
void doStuff (Cat B) {
B = new Cat (); / / Не повлияет на ссылку A
}
Это просто значит, что B указывает на другой объект. A по-прежнему счастлива.
Так что повторяйте за мной:
Java передает все по значению.
(Хорошо, еще раз... с чувством.)
Java передает все по значению.
Для примитивных типов — вы передаете копию текущего значения, для ссылок на объекты — вы передаете копию ссылки (дистанционного управления). Вы никогда не передаете объект. Все объекты хранятся в куче. Всегда.
Теперь заварите здоровенную чашку кофе и пишите код!
Оригинал статьи.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ