Изменяется ли массив в методе? - PullRequest
14 голосов
/ 20 августа 2011

Когда я пишу так:

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;
    }
}

печатает х22;

Когда я пишу так:

public class test {

    void mainx()
    {
        int fyeah = 5;
        smth(fyeah);
        System.out.println("x"+fyeah);
    }

    void smth(int fyeah)
    {
        fyeah = 22;
    }
}

Он не печатает x22, а печатает x5.

Почему во второй версии функции значение не изменяется? Изменяет ли он значения только для элементов массива?

Ответы [ 6 ]

22 голосов
/ 20 августа 2011

Переменная fyeah в вашем первом примере содержит ссылку на массив (не массив), в то время как целое число fyeah во втором примере содержит целое число .

Поскольку Java передает все по значению , произойдет следующее:

В случае массива: Копия ссылки на массив будет отправлено, а исходный массив будет изменен.

В случае int: Копия , будет изменено целое число , а исходное целое числоне изменится.

2 голосов
/ 20 августа 2011

Хорошо. Int в Java (и на самом деле все языки, которые имеют строгую типизацию данных) является примитивным типом данных. Это просто одна переменная этого типа данных. В Java это означает, что он передается по значению методу. Поэтому, когда вы передаете аргумент, создается копия переданной переменной. Любые операции, выполняемые в методе, действуют на эту копию, а не на переданную переменную.

На самом деле в Java ВСЕ передается по значению, но вдаваться в детали того, как это на самом деле верно с тем, что я собираюсь сказать дальше, кажется нецелесообразным.

С массивом ... это набор переменных примитивного типа данных int. Таким образом, полная копия массива на самом деле не является копией ссылки на память, в которой хранится массив. так что да, значение int IN в массиве отличается от операций в методе.

В коротких методах не изменяйте внешнее значение примитивов (int, float, double, long, char) с помощью операций в методе, вы должны вернуть результирующее значение этих операций вызывающей стороне, если вы хотите получить его. Операции меняют значение с большинством объектов, а также с массивами примитивов. Надеюсь, это поможет. На самом деле не уверен, как низкий уровень, чтобы получить. Может быть, кто-то еще может четко объяснить, почему именно по стоимости. Я "понимаю" это, но мне трудно помочь другим людям понять.

2 голосов
/ 20 августа 2011

Это потому, что ваш int является примитивом, а метод smth создает локальную копию, поэтому он печатает не так, как вы хотите.Объекты также передаются по значению, но по значению указателю в памяти.Поэтому, когда он изменяется, указатель остается в обоих методах, и вы видите изменение. Подробнее здесь

1 голос
/ 20 августа 2011

Думайте об этом с точки зрения памяти: давайте проанализируем вашу первую программу -

В mainx, fyeah - это массив int s, поэтому это ссылка (или указатель, если можно). Эта ссылка указывает на место в памяти кучи, где хранится фактический массив int s. Скажем, по адресу 100. Смежные отсюда расположены три целых (скажем, начиная с адресов 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.

0 голосов
/ 20 августа 2011

Видя это немного менее технически, я бы сказал, что

    fyeah[0] = 22;

изменяет содержимое (объекта, на который указывает) fyeah, а

    fyeah = 22;

меняется (переменная) фаях сама.
Другой пример:

void smth(Person person) {
    person.setAge(22);
}

меняет (содержание) человека, в то время как

void smth(Person person) {
    person = otherPerson;
}

изменяет переменную person - исходный экземпляр Person по-прежнему не изменяется (и, поскольку Java передается по значению, переменная в вызывающем коде не изменяется этим методом)

0 голосов
/ 20 августа 2011

int является типом значения, поэтому 5 передается непосредственно в smth, который может изменять только локальную копию. С другой стороны, массив является ссылочным типом, поэтому элементы этого массива могут быть изменены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...