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

Передача параметров в 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, 09:08
а что происходит, если передавать Integer или String? Это же объекты, т.е. тоже передаются их ссылки. Со String еще примерно понятно, он immutable, но почему Integer не получается поменять в методе так, чтобы изменение было видно в main?
Denis Rogov
Уровень 1
Expert
7 октября 2022, 14:04
тот же вопрос
callmemiku Java Developer в AT Consulting
31 октября 2022, 13:32
Integer тоже неизменяемый)
Vgoose
Уровень 22
21 сентября 2021, 13:00
Действительно не хватает картинок из статьи оригинала. Ну и можно дополнить понятиями стек, куча, адрес в куче (памяти).
Рустам
Уровень 27
21 сентября 2021, 10:02
Всё понятно изложено.Спасибо.
Mike-L
Уровень 43
20 апреля 2021, 02:20
Как "работают" методы линк
Alexandr
Уровень 19
5 февраля 2021, 14:30
Посмотрите оригинал статьи, там с картинками быстрее может дойти суть статьи.
Barm
Уровень 38
5 февраля 2021, 05:27
Вот String - это же ссылочная переменная? Тогда почему, при передаче её в метод, в методе не меняется объект, что находится по этой ссылке, а, судя по результату, действия происходят над его (объекта) копией?
edededed4
Уровень 0
24 февраля 2021, 09:21
Не уверен, что я прав, но суть в том, что - 1. В яве при изменении строки не происходит модификация обьекта, а создается новый обьект строки с новым значением (которое было найдено после операции). Поэтому часто используют стрингбилдер. 2. Строка также передается как адрес на обьект. В функции создается новая ссылка с тем же адресом (который передали), и эта ссылка смотрит на ту строку со старым значением. При модификации строки в методе создается новый обьект с новым значением и адресом, и ссылке в методе присваивается адрес этого нового обьекта. Но адрес этого нового обьекта не присваивается ссылке в основной части программы.
Dude QA Automation Engineer в Amazon
23 марта 2021, 07:22
В данной статье об этом как раз и написано, ВСЁ ПЕРЕДАЕТСЯ ПО ЗНАЧЕНИЮ, хоть это объект КОТ, хоть это строка (объект) СТРИНГ.
edededed4
Уровень 0
27 марта 2021, 22:24
Да, по значению, только у стринга чуть другое поведение при модификаци, чем у других объектов. И при передаче объекта передается значение адреса объекта, а не значение атрибутов.
Yaroslav
Уровень 29
17 октября 2021, 18:45
Потому что String - неизменяемый тип.
Alexander Java Developer
8 января 2021, 16:00
Если прочитав статью, вы сумеете с легкостью ответить на вопрос - что в итоге будут содержать переменные 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; } }
FrUshak Java Developer
16 марта 2021, 12:28
В чем же тут криминал, противоречащий статье? Вы вызвали метод, в котором сначала наполнили x1, а потом х2 сослали на экземпляр х1, таким образом ничего не поменяли, x2 вообще будет считаться неиспользуемой. А в выводе будет все то же значение "100" у х1, и нифигашечки у х2 Вы можете даже после присваивания, написать что то типа:
x2.push (new Integer ("200"));
и это просто добавит значение 200 в стек х1, а в х2 будет попрежнему пусто
Alexander Java Developer
19 марта 2021, 12:16
Нет никакого криминала, просто мне статья не дала понимания этого момента.
vinsler
Уровень 35
Expert
17 августа 2021, 19:40
public static void main(String[] args) { int a, b; // Integer a = 5; b = a; System.out.println(a + " " + b); } Вывод: 5 5 ==================================== А в чем собственно был вопрос? ))) Что выведется или какое значение будет лежать в переменной? Или на какую область памяти оно будет ссылаться? В переменной будет лежать ссылка на значение, которое присвоено первой переменной. Что с объектами, что с примитивами.
Anonymous #382798
Уровень 41
15 сентября 2020, 17:34
1. Передача значение по ссылке (ByRef) - передается ссылка на объект 2. Передача параметров по значению(ByVal) - передаётся копия значения В Java все параметры передаются по значению. Во многих других языках (C++, VisualBasic) можно выбирать способ передачи параметра… При передаче параметра в метод (или конструктор) по значению в Java создаётся его локальная копия, которая действует только в пределах метода (конструктора)
Vgoose
Уровень 22
21 сентября 2021, 13:05
я для себя усвоил это так В Java все параметры передаются по значению. Примитив - передается значение примитива Объект - передается значение ссылки (адрес памяти) на объект в куче
Анна
Уровень 34
22 ноября 2022, 14:21
в первом пункте, на сколько можно судить из всего вышесказанного, передается не ссылка на объект, а копия ссылки на объект. И теперь на некий объект ссылаются две одинаковых ссылки, одна из которых умрет, после окончания работы метода
Серега Android Developer
15 сентября 2020, 14:36
как добавить статью в закладки?
Серега Android Developer
15 сентября 2020, 14:37
на сайте
Anton Girin
Уровень 25
12 августа 2020, 10:14
Кстати, в статье не разобран пример как передается значение с: 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); в пул интеджеров? до и после упаковки и распаковки.