JavaRush /Java блог /Архив info.javarush /Передача параметров в Java
vincent_vega
24 уровень
Gainesville

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

Статья из группы Архив info.javarush
Переменная в 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 передает все по значению. Для примитивных типов — вы передаете копию текущего значения, для ссылок на объекты — вы передаете копию ссылки (дистанционного управления). Вы никогда не передаете объект. Все объекты хранятся в куче. Всегда. Теперь заварите здоровенную чашку кофе и пишите код! Оригинал статьи.
Комментарии (86)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
bazzzket Уровень 19 Expert
28 августа 2022
а что происходит, если передавать Integer или String? Это же объекты, т.е. тоже передаются их ссылки. Со String еще примерно понятно, он immutable, но почему Integer не получается поменять в методе так, чтобы изменение было видно в main?
Vgoose Уровень 22
21 сентября 2021
Действительно не хватает картинок из статьи оригинала. Ну и можно дополнить понятиями стек, куча, адрес в куче (памяти).
Рустам Уровень 27
21 сентября 2021
Всё понятно изложено.Спасибо.
Mike-L Уровень 43
20 апреля 2021
Как "работают" методы линк
Alexandr Уровень 19
5 февраля 2021
Посмотрите оригинал статьи, там с картинками быстрее может дойти суть статьи.
Barm Уровень 38
5 февраля 2021
Вот String - это же ссылочная переменная? Тогда почему, при передаче её в метод, в методе не меняется объект, что находится по этой ссылке, а, судя по результату, действия происходят над его (объекта) копией?
Alexander Уровень 33
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 создаётся его локальная копия, которая действует только в пределах метода (конструктора)
Серега Уровень 20
15 сентября 2020
как добавить статью в закладки?
Anton Girin Уровень 25
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); в пул интеджеров? до и после упаковки и распаковки.