Пользователь vincent_vega
vincent_vega
24 уровень
Gainesville

Передача параметров в Java

Статья из группы Архив info.javarush.ru
Переменная в Java — это контейнер, со значением в нем. Так что значит «передать» переменную? И какова разница между примитивными и ссылочными типами данных.
Передача параметров в Java - 1
Мы доберемся до этого позже. Давайте сначала начнем с простого присваивания. Что делает данный код:

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 передает все по значению. Для примитивных типов — вы передаете копию текущего значения, для ссылок на объекты — вы передаете копию ссылки (дистанционного управления). Вы никогда не передаете объект. Все объекты хранятся в куче. Всегда. Теперь заварите здоровенную чашку кофе и пишите код! Оригинал статьи.
Комментарии (83)
Чтобы просмотреть все комментарии или оставить свой,
перейдите в полную версию
Mike-L 17 уровень
20 апреля 2021
Как "работают" методы линк
Alexandr 19 уровень, Минск
5 февраля 2021
Посмотрите оригинал статьи, там с картинками быстрее может дойти суть статьи.
Barm 16 уровень, Минск
5 февраля 2021
Вот String - это же ссылочная переменная? Тогда почему, при передаче её в метод, в методе не меняется объект, что находится по этой ссылке, а, судя по результату, действия происходят над его (объекта) копией?
Alexander 29 уровень, Москва
8 января 2021
Если прочитав статью, вы сумеете с легкостью ответить на вопрос - что в итоге будут содержать переменные s1 и s2, то я сильно удивлюсь, а жаль. public class TestClass{ public static void main(String args[]){ Stack s1 = new Stack (); Stack s2 = new Stack (); processStacks (s1,s2); System.out.println (s1 + " "+ s2); //тут } public static void processStacks(Stack x1, Stack x2){ x1.push (new Integer ("100")); //assume that the method push adds the passed object to the stack. x2 = x1; } }
Anonymous #382798 41 уровень
15 сентября 2020
1. Передача значение по ссылке (ByRef) - передается ссылка на объект 2. Передача параметров по значению(ByVal) - передаётся копия значения В Java все параметры передаются по значению. Во многих других языках (C++, VisualBasic) можно выбирать способ передачи параметра… При передаче параметра в метод (или конструктор) по значению в Java создаётся его локальная копия, которая действует только в пределах метода (конструктора)
Серега 19 уровень, Кривой Рог
15 сентября 2020
как добавить статью в закладки?
Anton Girin 24 уровень, Рязань
12 августа 2020
Кстати, в статье не разобран пример как передается значение с: 1) int x = 5; doStuff(x); void doStuff(Intrger y){} ?? А я боюсь, что на собесе именно об этом и спросят. Так то, я думаю, что копируется значение, а не ссылка. То есть мы скопировали значение и после жава автоупаковала. Но тогда напрашивается другой вопрос. Как передастся значение: 2) Integer integer = new Integer(6); doStuff(integer); void doStuff(Intrger y){} и 3) Integer integer = new Integer(6); doStuff(integer); void doStuff(int y){} 4) Integer integer = 6; doStuff(integer); void doStuff(int y){} и попадает ли значение Integer integer = 6; и Integer integer = new Integer(6); в пул интеджеров? до и после упаковки и распаковки.
S 22 уровень, Минск Expert
19 июля 2020
Двадцать минут читал ЭТО пока разобрался, что автор хочет донести. Потом только дошло (а я этот материал уже давно знаю). Представляю каково для тех, кто начинает учиться. Особенно здесь:

Со ссылками вы тоже получаете копию содержимого.
Но что такое содержимое ссылки?
Так что теперь все, что B делает объекту Cat, повлияет на Cat, на который указывает A, но это не повлияет на содержимое A!
Это же надо так запутать!!! Какую копию содержимого? "Содержимое" в человеческом понятии может быть у объекта, а у ссылка - это указатель на содержимое. Проще так: каждый новый объект, создаваемый по new - это отдельная ячейка в памяти. Делая Cat a = new Cat (); вы создаете ссылку a типа Cat, создаете новый объект new Cat() - в конкретной ячейке в памяти(у каждой ячейки есть свой адрес), и делая "=" ваша ссылка указывает на данную ячейку, где лежит созданный объект Cat(); Cat b = a; - В данном случае вы создаете ссылку b типа Cat и делаете, что она указывает на ту же ячейку, что и a. Соответственно, если вы будете менять какие-то поля класса - вы можете делать это и через ссылку а, и через ссылку b (например a.setName или b.setName), так и получать и тот же результат (System.out.println(a.getName) или System.out.println(b.getName)). Результат будет один и тот же - так как обе ссылки указывают на того же ОДНОГО физического кота (ячейку в памяти). НО как только вы потом делаете b = new Cat(); - всё, вы создали нового физического кота по new (ячейку в памяти) и привязали ссылку b к ДРУГОМУ коту. Теперь a и b отношения друг другу не имеют.
Anton Povarnitsin 7 уровень
23 мая 2020
Что такое new???
Alex 17 уровень, Москва
17 мая 2020
Оч хорошо разложено!