Изменение значений переменных в методах, Java

У меня возникает вопрос об изменении значений переменных в методах в Java.

Это мой код:

public class Test {
    public static void funk(int a, int[] b) { 
        b[0] = b[0] * 2; 
        a = b[0] + 5;
    } 

    public static void main(String[] args) {
        int bird = 10;
        int[] tiger = {7};

        Test.funk(bird, tiger);
    }
}

После выполнения метода Test.funk(bird, tiger) значение птицы не изменяется - оно остается со значением 10, хотя в методе funk() мы изменили значение с помощью a = b[0] + 5;

С другой стороны, значение элемента в массиве изменяется, потому что мы имеем оператор b[0] = b[0] * 2;

Я не понимаю, почему одна вещь меняется, а другая нет? Не мог бы кто-нибудь объяснить это мне.

Ответ 1

Посмотрите на статью Джона Скита о "Передача параметров в Java" , которая объясняет это.

Короче (посмотрите на его сайт для более подробного объяснения):

Массивы являются ссылочными типами. Если вы передаете ссылку, указывающую на массив, значение ссылки копируется и присваивается параметру функции. Таким образом, параметр будет указывать на тот же массив, что и переданный аргумент. Таким образом, изменения, которые вы вносите в массив через параметр вашей функции, будут видны в вызывающей функции. Однако изменение самого параметра (b), например, путем установки его на нуль, не будет замечено вызывающей функцией, поскольку параметр (b) является только копией переданного аргумента (тигра).

Целые являются так называемыми примитивными типами. Передача целого числа копирует его значение и присваивает его тоже параметру. Но это значение не относится к фактическим данным, а относится к самим данным. Таким образом, изменение параметра в функции влияет на параметр (a), но не на аргумент, переданный в вызывающей функции (птица).

Ответ 2

Это потому, что когда вы объявляете

 public static void funk(int a, int[] b) 

Объем переменной a - это только этот метод. Затем, когда вы изменяете значение, вы изменяете только значение , которое в , которое.

О b. Это новая ссылка на объект для того же массива, созданного в основном, поэтому кажется, что значение меняет (что меняется - объект массива под ним)

Но попробуйте следующее:

public static void funk(int a, int[] b) { 
    // create a new reference for b
    int[] c = new int[b.length];
    c[0] = b[0];
    b = c;

    // The same.
    b[0] = b[0] * 2; 
    a = b[0] + 5;
} 

Когда вы это сделаете, значение тигра не изменится (только содержимое нового массива c, созданного в funk)

Вы можете смоделировать пропуск через ref с помощью обертки. Посмотрите это сообщение.

Хотя у меня нет комментариев об этом

EDIT Просто для удовольствия:

Я изменил ваш код, чтобы использовать обертку, опубликованную выше.

Это выглядит довольно странно, но похоже, что он работает.

// By ref simulated.
public class Test {

    public static void funk(_<Integer> a, int[] b) { 
        b[0] = b[0] * 2; 
        a.s(  b[0] + 5 ) ;
    } 

    public static void main(String[] args) {
        _<Integer> bird = new _<Integer>(10);
        int[] tiger = {7};

        Test.funk( bird , tiger );

        System.out.println("bird = " + bird );
        System.out.println("tiger = " + tiger[0] );

    }

}

Печать

bird = 19
tiger = 14

: - S

Ответ 3

В принципе, объекты (например, массивы) передаются в методы "по ссылке". Поэтому, когда вы меняете объект, он меняет тот же объект, который был передан в метод.

Примитивы (например, int) "передаются по значению", поэтому переменная, которую вы присваиваете значению в a, не совпадает с переменной int, которая была передана.

Надеюсь, это поможет...