Подтвердить что ты не робот

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

Я знаю, что Java всегда передается по значению, но я не понимаю, почему это работает:

public static void swap(int[] arr, int i, int j)
{
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static void main(String[] args)
{
    int[] arr = {3, 4, 5, 6};
    swap(arr, 1, 3);
    // arr becomes {3, 6, 5, 4}
}

И это не работает:

public static void swap(int[] arr, int[] arr2)
{
    int[] tmp = arr;
    arr = arr2;
    arr2 = tmp;
}
public static void main(String[] args)
{
   int[] arr = {3, 4, 5, 6};
   int[] arr2 = {1, 2, 5, 6};
   swap(arr, arr2);
}

Почему?

4b9b3361

Ответ 1

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

Первый метод работает правильно, потому что он изменяет объект, на который ссылается массив (который является изменяемым), он не меняет сама ссылка.

Откажитесь от этот пост в блоге для получения более подробной информации о различиях между передачей по значению и передачей по ссылке.

Ответ 2

Ваш первый пример - перенос значений в массиве.

Второе, что вы пытаетесь изменить ссылку (массивы - это объекты в Java). Ссылки являются локальными копиями (pass-by-value) и не влияют на контекст calee.

(вопрос № 56.903 о вызове по значению, Stackexchange должен открыть PassByValue.com; -)

Ответ 3

Если вы когда-либо использовали C или С++ и знали о том, как работают указатели, то, что сделал для меня весь этот сценарий, следующее утверждение:

In Java, everything is passed by value. 
In case of Objects, the reference (pointer) is passed by value.

Таким образом, в основном функция подкачки

public void swap(int[] a, int[] b)
{
    etc.
}

Будет просто получить указатель на массив a int [] и указатель на массив b int []. Вы просто меняете два указателя. Вы не можете изменять содержимое указателей, подобных этому.

В основном эквивалент C

void swap(int* a, int* b)
{
   int* temp = a;
   a = b;
   b = temp;
}

int main(void)
{
    int a[] = {5,6,7,8};
    int b[] = {1,2,3,4};
    swap(a,b);
}

Хотя даже в C это будет работать только так:

void swap(int** a, int** b)
{
   int* temp = (*a);
   (*a) = (*b);
   (*b) = temp;
}

int main(void)
{
    int a[] = {5,6,7,8};
    int b[] = {1,2,3,4};
    swap(&a, &b);
}

Конечно, вы не можете отправить ссылку ссылки на Java. Указатели в этом смысле не существуют в Java.

Поэтому, чтобы фактически изменить объект в другой функции, вам понадобится объект "Держатель", которому копируется ссылка, но ссылка внутри него на объект, который вы хотите изменить, на самом деле является фактической ссылкой на объект, если это имеет смысл.

И, таким образом, будет работать следующее:

public class ArrayHolder
{
    public int[] array;

    public ArrayHolder(int[] array)
    {
        this.array = array;
    }
}

public void swap(ArrayHolder a, ArrayHolder b)
{
    int[] temp = a.array;
    a.array = b.array;
    b.array = temp;
}

public static void main(String[] args)
{
    ArrayHolder aaa = new ArrayHolder(new int[] {5,6,7,8});
    ArrayHolder bbb = new ArrayHolder(new int[] {1,2,3,4});
    swap(aaa,bbb);
}

Ответ 4

  • Первый своп вы меняете данные массива. (ссылается на arr: ссылка), поэтому он модифицируется

  • Второй своп, вы меняете arr, arr2, две локальные переменные. поэтому, когда вы выходите из метода, две новые переменные уничтожаются

Ответ 5

  • Arr и arr2 являются локальными переменными, поэтому они будут уничтожены при завершении метода свопинга.
  • Внешний метод свопинга не влияет на локальные переменные.