Как сохранить изменения массива, которые были сделаны внутри функции? - PullRequest
0 голосов
/ 13 сентября 2018

Мне нужно создать класс для работы с массивами статическими обобщенными методами. Например, в этой функции мне нужно вставить один массив (arr2) внутри другого (arr1) в некоторый индекс (место).

public static<T> void paste(T[] arr1, int place, T[] arr2) {
        Object[] temp = new Object[arr1.length + arr2.length];
        System.arraycopy(arr1, 0, temp, 0, place);
        System.arraycopy(arr2, 0, temp, place, arr2.length);
        System.arraycopy(arr1, place, temp, place+arr2.length, arr1.length-place);

        arr1 = (T[])temp;
    }

Функция работает правильно, но я не вижу изменений в основной функции. Результат всегда остается в функции вставки. Что я могу сделать в этой ситуации?

public static void main(String[] args) {
        Integer arr[] = {1 ,2 ,3 ,4, 5};
        Integer arr2[] = {11 ,22 ,33 ,44, 55};

        paste(arr, 2, arr2);
        show(arr);

    }

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

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

public static<T> T[] paste(T[] arr1, int place, T[] arr2) {
  // your code here
return temp;
}

Если вы не хотите изменять подписьметод, который является правильной вещью.Но если мы предположим, что по какой-то причине вы не хотите этого делать.Затем вам нужно изменить фактический массив, который передается в качестве аргумента.В вашем конкретном примере вы не можете сделать это, потому что ни arr1, ни arr2 не имеют адекватного размера.Но это был бы путь к более процедурному типу решения.

Пример процедуры, которая изменяет свой аргумент:

public void mutationProcedure(int array[],int position, int changeToValue) {
    array[position] = changeToValue;
}

В этом коде, если мы вызываем его извнезначение массива будет изменено.

ОБНОВЛЕНИЕ: Решение без необходимости явного приведения.Я считаю, что это лучшее решение.

public static<T> T[] paste(T[] arr1, int place, T[] arr2) {
        T[] temp = Arrays.copyOf(arr1, arr1.length + arr2.length);
        System.arraycopy(arr2, 0, temp, place, arr2.length);
        return temp;
}

Сначала мы создадим новый массив, начинающийся с arr1, а размер равен обоим массивам.Затем мы копируем второй массив с позиции конца array1 до конца.Так как класс Arrays работает с обобщениями, нам не нужно явно приводить.

0 голосов
/ 13 сентября 2018

Вы не можете изменить длину существующего массива.Поэтому метод paste должен возвращать новый массив:

public static<T> T[] paste(T[] arr1, int place, T[] arr2) {
    ...

    return temp;
}

Затем в методе main вы присваиваете возвращаемое значение новой переменной и используете его:

T[] result = paste(arr, 2, arr2);
show(result);

Конечно, вы также можете присвоить возвращаемое значение существующей переменной, то есть:

arr = paste(arr, 2, arr2);
show(arr);

Почему это не работает так, как вы это пробовали:

Если вы переназначите arr1 в методе paste, это не повлияет на вызывающий метод.Он изменит только локальную переменную (фактически значение параметра) внутри метода. ссылка в вызывающем методе (main) не может быть изменена из другого метода.


Относительно создания экземпляра универсального массива:

Вы можете создать экземпляр массива "правильного" типа (вместо массива Object с)используя отражение:

T[] temp = (T[]) Array.newInstance(arr1.getClass().getComponentType(), arr1.length + arr2.length);

Обратите внимание, что вам все еще нужно приведение, но тип времени выполнения массива будет таким же, как тип arr1.

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