Pure Danger Tech


navigation
home

Generics puzzler – array construction

27 Feb 2007

So, here’s my generics puzzler for the day. I’m not sure whether it’s possible to implement this method in a type-safe way or not:

<T> T[] mergeArrays(T[]... arrays)

The problem arises when you need to construct the new array, which requires creating an array of the proper type T. The first inclination is to write code that looks like this:

public static <T> T[] mergeArrays(T[]... arrays) {
        // Determine total length
        int length = 0;
        for(T[] array : arrays) {
            length += array.length;
        }
        
        // Create result array and copy data into it
        T[] result = new T[length];           // BROKEN: CANNOT USE T ON RHS
        for(int start=0,i=0; i<arrays.length; i++) {
            T[] array = arrays[i];
            System.arraycopy(array, 0, result, start, array.length);
            start += array.length;
        }
        
        return result;
    }

You might try writing a variant of this with either raw collections or an Object array, then cast to the desired array type:

public static <T> T[] mergeArrays(T[]... arrays) {
        List<T> result = new ArrayList<T>();
        
        for(T[] array : arrays) {
            for(T item : array) {
                result.add(item);
            }
        }        
        // BROKEN: This generates a compiler warning about checking against an erased type
        return (T[])result.toArray();
    }

That warning is important as you will receive an Object[], not a T[] array, meaning that callers do not receive an array of the expected type. Same problem occurs in the array form – you could construct an array of type Object[] and cast to T[], but you will receive an Object[] from the method, not a String[] or whatever specific type you want.

I think you might be able to use type tokens or super type tokens to extract the generic type parameter, then construct the array reflectively with java.lang.reflect.Array#newInstance(). But I haven’t figured out the magic invocation on how to do this.

So I ask you great Internet in the sky, is this possible?