Переменная в 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 передает все по значению.
Для примитивных типов — вы передаете копию текущего значения, для ссылок на объекты — вы передаете копию ссылки (дистанционного управления). Вы никогда не передаете объект. Все объекты хранятся в куче. Всегда.
Теперь заварите здоровенную чашку кофе и пишите код!
Оригинал статьи.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Я бы написал немного по другому. Например: В Java данные бывают двух типов — примитивного и ссылочного типа. Рассмотрим разницу между ними. Примитивный тип хранит в себе значение данных, пример:
т.е. в переменной x лежит число «3» (x = «3»).
Ссылочный тип хранит в себе ссылку на место в памяти, где лежит значение данных, пример:
т.е. в переменной y лежит не число «3», а ссылка на место в памяти, где записано число «3» (y = ссылка -> «3»)
Об этом надо помнить при работе с разными типа данных.
Рассмотрим некоторые примеры:
1. Присваивание.
В результате данных операций значение x1 и y1 равны «3». Но есть нюанс:
в x1 мы скопировали значение — «3» (x1 = «3»)
в y1 мы скопировали ссылку на значение «3» (y1 = ссылка -> «3»)
поэтому после действий:
значение x1 не изменится, останется «3»;
значение y1 также измениться, будет «5», т.к. мы изменили не ссылку, а значение, на которое ссылаются и y, и y1.
2. Передача переменных в методы.
В Java переменные передаются в методы по значению, это значит «скопировать значение и передать копию».
Но для примитивных типов данных копируются значения, а для ссылочных — ссылки на значения.
Рассмотрим пример функции:
Применим функцию к нашим переменным:
После
Везде присваивание типу String число надо брать в двойные кавычки.
String y = «3»;
и т.д.
Вывод:
Что не так?
В Java String immutable, т.е. в строке в функции
создается новый объект и его ссылка присваивается b.
У y ссылка остается на старый объект, т.е. «3».
LINK
1. есть полноценные объекты, при передаче которых в качестве прараметра методу передается только копия ссылки на них. При манипуляциях с их состоянием внутри этого метода все изменения отражаются на исходном объекте.
2. есть примитивы, при передаче которых методу в качестве параметров передаются копии их значения. При манипуляциях внутри метода с этим значением, иходное значение примитива не меняется.
3. и есть некие особые «недообъекты» (строки и примитивы заключенные в «обертки»), при передаче которых методу хотя и создается копия ссылки на них, но при манипуляциях внтури метода изменеие исходного объекта не происходит.
Получается, что способ передачи по значению или по ссылке не имеет принципиального, результирующего значения? Т.е. будет ли исходный объект изменен или нет, зависит не от того, как он был передан методу, а лишь от задумки создателей языка?
1. Примитивы — в метод передается копия. Манипуляции в методе с копией никак не влияет на оригинал.
2. Объекты — в метод передается ссылка на объект. Если в объекте есть метод, который меняет содержимое полей объекта и этот метод применяется, то меняется объект, на который ссылается и оригинал, и копия.
Пример:
выдает:
В объектах String и оберток нет таких методов, чтобы изменить такие переменные мы просто всегда создаем новый объект, теряя ссылку на старый.
Создаем переменную a и новый объект «3», данная строка идентична:
В переменную a записываем ссылку на новый объект «5», ссылка на «3» теряется. Данная строка идентична:
P.S. String хранит в себе ссылку на массив из char. К тому же этот массив final — т.е. его изменить невозможно.
Если интересно — посмотри строение класса String.
Это вообще как?
А ведь содержит ссылку на объект Cat, следовательно если как-то мы поменяем Cat посредством действий над В, то и поменяется содержимое А, ведь они оба ссылаются на один объект?