Изменяется ли массив в методе?
Когда я пишу вот так:
public class test {
void mainx()
{
int fyeah[] = {2, 3, 4};
smth(fyeah);
System.out.println("x"+fyeah[0]);
}
void smth(int[] fyeah)
{
fyeah[0] = 22;
}
}
Он печатает x22;
Когда я пишу вот так:
public class test {
void mainx()
{
int fyeah = 5;
smth(fyeah);
System.out.println("x"+fyeah);
}
void smth(int fyeah)
{
fyeah = 22;
}
}
Он не печатает x22, а печатает x5.
Почему во второй версии функция не меняет значение? Изменяет ли значения только элементы массива?
Ответы
Ответ 1
Переменная fyeah
в первом примере содержит ссылку на массив (а не массив), а целое число fyeah
во втором примере содержит целое число.
Так как Java передает все по значению, произойдет следующее:
В случае с массивом: Будет отправлена копия ссылки на массив, и исходный массив будет изменен.
В случае int: Копия целого будет изменена, а исходное целое не будет изменено.
Ответ 2
Это потому, что ваш int является примитивным, а метод smth
создает локальную копию, поэтому он не печатает так, как вы хотите. Объекты также передаются по значению, но значение указателя в памяти. Поэтому, когда он изменяется, указатель остается в обоих методах, и вы видите изменение. Подробнее здесь
Ответ 3
Ok. Int в java (и на самом деле все языки с строгим набором данных) - это примитивный тип данных. Это всего лишь одна переменная этого типа данных. В java это означает, что он передан по значению методу. Поэтому, когда вы передаете аргумент, создается копия переданной переменной. Любые операции, выполняемые в методе, действуют на эту копию, а не на переданную переменную.
Фактически в java ВСЕ передается по значению, но вхождение в детали того, как это на самом деле истинно, с тем, что я собираюсь сказать, кажется неприемлемым.
С массивом... его набор переменных типа примитивных данных int. Таким образом, целая копия массива фактически не делается просто копией ссылки на память, в которой хранится массив. поэтому да значение int IN массива изменяется от операций в методе.
В коротких методах не изменяются внешние значения примитивов (int, float, double, long, char) с операциями в методе, вы должны вернуть полученное значение этих операций вызывающему, если вы хочу его получить. Операции изменяют значение для большинства объектов, а также массивов примитивов. Надеюсь, это поможет. Действительно не уверены в том, как низкий уровень. Может быть, кто-то еще может четко объяснить, почему его по стоимости. Я "получаю" это, но мне трудно помочь другим людям понять.
Ответ 4
int
- это тип значения, поэтому 5 передается непосредственно в smth
, который может изменять только локальную копию. Массив, с другой стороны, является ссылочным типом, поэтому элементы этого массива могут быть изменены.
Ответ 5
Увидев это немного менее технически, я бы сказал, что
fyeah[0] = 22;
изменяет содержимое (объект, на который указывает) fyeah, а
fyeah = 22;
изменяется (переменная) сама fyeah.
Другой пример:
void smth(Person person) {
person.setAge(22);
}
меняет (содержимое) человека, пока
void smth(Person person) {
person = otherPerson;
}
меняет переменную person - исходный экземпляр Person по-прежнему остается неизменным (и, поскольку Java имеет значение pass-by-value, переменная в вызывающем коде не изменяется этим методом)
Ответ 6
Подумайте об этом с точки зрения памяти: проанализируем вашу первую программу -
В mainx
, fyeah
- это массив int
, поэтому его ссылка (или указатель, если я могу). Эта ссылка указывает на местоположение в памяти кучи, где хранится фактический массив int
. Скажем, по адресу 100. Находится смежно отсюда три ints (скажем, начиная с адреса 100, 104 и 108 соответственно являются 2, 3 и 4).
Теперь вы вызываете свой метод smth
и передаете ссылку. Внутри метода есть другая ссылка (типа массива int
) с именем fyeah
. Этот fyeah
отлично отличается от справочника fyeah
в методе mainx
. Теперь, когда вы вызываете smth
и передаете fyeah
из mainx
, fyeah
внутри метода smth
инициализируется, чтобы указывать на то же местоположение (то есть адрес памяти 100)
Когда вы получаете доступ к элементу 0 из fyeah
и присваиваете ему значение 22, он достигает области памяти 100 и записывает это значение 22. Когда вы вернетесь в свой метод mainx
, ссылка fyeah
по-прежнему относится к адресу памяти 100. Но значение, присутствующее в этом месте, теперь равно 22. Таким образом, вы получаете это значение при доступе к первому элементу из fyeah
в mainx
.
Теперь, ваша вторая программа. Ваш метод mainx
объявляет int
(а не массив, но простой int
) и устанавливает его в 5. Эта переменная fyeah
создается в стеке, а не в куче. Значение 5 сохраняется в стеке. Теперь вы вызываете smth
и передаете эту переменную. В рамках метода smth
вы снова объявляете переменную int
, fyeah
по имени (в качестве аргумента формального метода). Опять же, это отличается от fyeah
метода mainx
, и этот fyeah
также создается в стеке. Эта переменная будет инициализирована значением 5, скопировано из fyeah
, которое вы передали в smth
как аргумент. Обратите внимание, что на fyeah
есть две разные копии, как на стек, так и на значение 5. Теперь вы назначаете fyeah
в smth
значение 22. Это не повлияет на fyeah
mainx
, поэтому, когда вы вернетесь к mainx
и получите доступ к fyeah
, вы увидите 5.