Concatenation and type of casting

I have a class utility :

public class ArrayUtils {
    public static <T> T[] concat(T[]... arrays) {
        if(arrays == null) {
            return null;
        }
        int size = 0;
        for(T[] array : arrays) {
            size += array.length;
        }

        T[] concatenatedArray = (T[]) new Object[size];

        int i = 0;
        for(T[] array : arrays) {
            for(T item : array) {
                concatenatedArray[i++] = item;
            }
        }

        return concatenatedArray;
    }
}

When I test concat , it breaks:

public class ArrayUtilsTest extends TestCase {

    public void testConcat() throws Exception {
        Integer[] first = new Integer[]{1,2,3};
        Integer[] second = new Integer[]{4,5,6};
        Integer[] concat = ArrayUtils.concat(first, second);
        assertEquals(6, concat.length);
    }
}

with message

java.lang.ClassCastException: java.lang.Object [] cannot be dropped java.lang.Integer []

I guess this is due to generics. Could you offer suggestions for his work? In addition, the background will be excellent.

Thank!

+4
source share
5 answers

Your problem is that you create an array Objectin your method concat.

Instead

T[] concatenatedArray = (T[]) new Object[size];

use

T[] concatenatedArray = (T[]) Array.newInstance(arrays[0].getClass()
        .getComponentType(), size);

UPDATE: While the above will probably do the job for you, newacct pointed out in the comments that it is even better / safer to use

T[] concatenatedArray = (T[]) Array.newInstance(arrays.getClass()
        .getComponentType().getComponentType(), size);

, . ArrayUtils.concat(new String[]{"foo"}, new Integer[]{42}); ( ), ArrayStoreException.

, , T, , .

, .

public static <T> T[] concat(T[] array1, T[]... arrays);

: , java, . https://docs.oracle.com/javase/tutorial/java/generics/genMethods.html.

concat ( Object[] Integer[]), - - Object[] ( , ).

, , Integer[] ( ;)), .

, : : , , Apache Commons , . , - ;)

+2

T arrays , :

T[] concatenatedArray = (T[]) Array.newInstance(arrays.getClass()
    .getComponentType().getComponentType(), size);
+2

, , JRE:

public static <T> T[] concat(T[] first, T[]... arrays) {
    int size = first.length;
    for(T[] array : arrays) size += array.length;
    if(size==first.length) return first.clone();
    ArrayList<T> list=new ArrayList<>(size);
    Collections.addAll(list, first);
    for(T[] array: arrays) Collections.addAll(list, array);
    return list.toArray(first);
}

toArray List, , , . , , , , , .

List ...

+1

,

T[] concatenatedArray = (T[])Array.newInstance(arrays[0][0].getClass(), size);

array T[]... arrays , Final Array

0

ArrayUtilsTest TestCase {

public void testConcat() throws Exception {
    Integer[] first = new Integer[]{1,2,3};
    Integer[] second = new Integer[]{4,5,6};
//YOU need to cast the returned array from concat to an "Integer[]"
    Object[] a = ArrayUtils.concat(first, second);
    Integer[] concat = Arrays.copyOf(a, a.length, Integer[].class);

    assertEquals(6, concat.length);
}

}

-1
source

All Articles