Изменить массив, переданный как метод-параметр - PullRequest
6 голосов
/ 20 августа 2011

Предположим, у меня есть int-массив, и я хочу его изменить.Я знаю, что не могу назначить новый массив массиву, переданному в качестве параметра:

public static void main(String[] args)
{
    int[] temp_array = {1};
    method(temp_array);
    System.out.println(temp_array[0]); // prints 1
}
public static void method(int[] n)
{
    n = new int[]{2};
}

, в то время как я могу изменить его:

public static void main(String[] args)
{
    int[] temp_array = {1};
    method(temp_array);
    System.out.println(temp_array[0]); // prints 2
}
public static void method(int[] n)
{
    n[0] = 2;
}

Затем я попытался присвоить произвольный массивмассив передается как параметр, используя clone():

public static void main(String[] args)
{
    int[] temp_array = {1};
    method(temp_array);
    System.out.println(temp_array[0]); // prints 1 ?!
}
public static void method(int[] n)
{
    int[] temp = new int[]{2};
    n = temp.clone();
}

Теперь мне интересно, почему он печатает 1 в последнем примере, а я просто копирую массив с clone(), который просто копирует значение, а не ссылку,Не могли бы вы объяснить это для меня?


РЕДАКТИРОВАТЬ: Есть ли способ скопировать массив в объект без изменения ссылки?Я хочу напечатать последний пример 2.

Ответы [ 4 ]

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

Ваши примеры 1 и 3 практически совпадают в контексте вопроса - вы пытаетесь присвоить новое значение n (которое является ссылкой на массив, переданный по значению).

Тот факт, что вы клонировали массив temp, не имеет значения - все, что он сделал, это создал копию temp и затем присвоил ее n.

Чтобы скопировать значения в массив, переданный в ваш метод method, вы можете посмотреть: System.arraycopy

Все это, конечно, зависит отразмеры вашего массива n и того, который вы создаете в методе method.

Если предположить, что они оба имеют одинаковую длину, например, вы бы сделали это так:

public static void main(String[] args)
{
    int[] temp_array = {1};
    method(temp_array);
    System.out.println(temp_array[0]);
}
public static void method(int[] n)
{
    int[] temp = new int[]{2};
    System.arraycopy(temp, 0, n, 0, n.length); 
    // or System.arraycopy(temp, 0, n, 0, temp.length) - 
    // since we assumed that n and temp are of the same length
}
4 голосов
/ 20 августа 2011

В вашем методе

public static void method(int[] n)

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

Однако в фактическом методе

public static void method(int[] n) {
    int[] temp = new int[]{2};
    n = temp.clone();
}

Вы создаете новый массив и затем говорите, что «имя 'n' теперь указывает на этот, другой массив, а не на тот, который былпрошло в ".По сути, имя 'n' больше не является именем для массива, который был передан.

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

Как вы правильно заметили, вы не можете назначить ссылку на массив, переданную в качестве параметра. (Точнее, назначение не окажет никакого влияния на вызывающего.)

Это лучшее из того, что вы можете сделать:

public static void method(int[] n) {
    int[] temp = new int[]{2};
    for (int i = 0; i < temp.length; i++) {
        n[i] = temp[i];
    }
    // ... or the equivalent using System.arraycopy(...) or some such
}

Конечно, это работает правильно, только если размер входного массива совпадает с размером массива, который вы копируете в него. (То, как вы должны справиться с этим, будет зависеть от конкретного приложения ...)


Для записи Java передает ссылку на массив по значению. Он не передает содержимое массива по значению. И клон не поможет решить эту проблему. (По крайней мере, не с подписью метода, как объявлено.)

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

В вашем методе method ничто из того, что вы назначаете для n, никогда не изменит значения объекта, переданного и присвоенного n.В начале method, n указывает на массив.Когда вы назначаете n равным другому массиву, вы просто перенаправляете, на какой массив указывает n, и ничего не изменили в temp_array из метода main.

...