0

I need to make a class for working with arrays with static generic methods. For example in this function I need to paste one array(arr2) inside other(arr1) at some index (place).

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

The function work correctly, but I cant see changes in main function. The result always remains in paste function. What can I do in this situation?

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

    }
I. Bilous
  • 57
  • 6

2 Answers2

3

You can't modify the length of an existing array. Therefore, the paste method must return the new array:

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

    return temp;
}

Then, in the main method, you assigne the returned value to a new variable and use it:

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

Of course, you can also assign the return value to the existing variable, i.e.:

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

Why it doesn't work the way you've tried it:

If you reassign arr1 within the paste method, it won't affect the calling method. It will only change the local variable (in fact a parameter value) within the method. The reference in the calling method (main) can't be changed from within another method.


Regarding the instantiation of the generic array:

You can instantiate an array of "correct" type (instead of an array of Objects) using reflection:

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

Note that you still need a cast, but the runtime type of the array will be the same as the type of arr1.

Alex Shesterov
  • 26,085
  • 12
  • 82
  • 103
1

When you pass arr1 you are passing a copy of the pointer of the array. Inside the method you are working with this pointer copy , not with the original pointer coming from the outer method. When you assign temp to arr1 you are assigning it to the copy not to the original, the original is still pointing to the other array.

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

If you don't want to change the signature of the method, which is the correct thing to do. But if we presume for some reason you don't want to do it. Then you need to mutate the actual array that is passed as argument. In your particular example you can not do it because neither arr1 neither arr2 are of adequate size. But this would have been the way to go for a more procedural type of solution.

Example of procedure that mutates its argument:

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

On this code if we invoke it from outside the array will have its value mutated.

UPDATE: Solution without the need for explicit casting. I believe it is the better solution.

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

First we create a new array starting with arr1 and size equals both arrays. Then we copy the second array from the position of array1 end to the end. Since Arrays class works with generics we don't need to cast explicitly.

Alexander Petrov
  • 9,204
  • 31
  • 70