Reputation: 927
public static <T> T[][] toTwoDim(T[] array)
The function signature as it is above.. It's a generic typed function, which can be used no matter what type is the data contained in the array. generally, it receives an array, and return a 2-dimensional array with its half elements in the first row, and the other half in the second row. I 've no idea how to implement it cause I could not create a generic typed 2-dimensional array inside the function. Some one help me out? Thanks!
Upvotes: 0
Views: 166
Reputation: 7579
You could do this, which doesn't require suppressing any warnings.
public static <T> T[][] toTwoDim(Class<T[][]> clazz, T[] array)
{
int halfLength = array.length / 2;
T[][] ret = clazz.cast(Array.newInstance(clazz.getComponentType().getComponentType(), 2, halfLength + 1));
System.arraycopy(array, 0, ret[0], 0, halfLength);
System.arraycopy(array, halfLength, ret[1], 0, array.length - halfLength);
return ret;
}
Upvotes: 0
Reputation: 927
I found the perfect solution:
@SuppressWarnings("unchecked")
public static <T> T[][] toTwoDim(T[] array) {
Class<T> ctype = (Class<T>) array.getClass().getComponentType();
int halfLength = array.length / 2;
T[][] ret = (T[][]) Array.newInstance(ctype, 2, 1);
T[] r1 = (T[]) Array.newInstance(ctype, halfLength);
T[] r2 = (T[]) Array.newInstance(ctype, array.length - halfLength);
ret[0] = r1;
ret[1] = r2;
for (int i = 0; i < halfLength; i++)
r1[i] = array[i];
for (int i = 0; i < array.length - halfLength; i++) {
r2[i] = array[i + halfLength];
}
return ret;
}
public static void main(String[] a) {
Integer[] bar = { 1, 2, 3, 4, 5 };
Integer[][] dims = toTwoDim(bar);
for (Integer[] r : dims) {
for (Integer d : r) {
System.out.print(d + " ");
}
System.out.println();
}
}
output:
1 2
3 4 5
the generic type of the 'toTwoDim' function is erased, but the incoming array's element type could be obtained via reflection!
Upvotes: 1
Reputation: 718788
It should be possible to do.
The basic approach is to use java.lang.reflect.Array.newInstance(clazz, dimX, dimY)
to create the array instance.
If you want the result array's base type to be the same as the base type of the argument, then use reflection to get the base type from array.getClass()
.
If you want the result array's base type to be <T>
, then you will need to add an extra argument to toTwoDim
whose type is Class<T>
, and use it to pass the class object for the desired array base type. (Type erasure means that it is not possible for the toTwoDim
method to determine the class object for <T>
at runtime. Passing the class object as an argument is the standard workaround.)
Upvotes: 1
Reputation: 77044
I played around with this for quite a bit, and my understanding, for reasons of type erasure, is that this isn't something that's possible.
Based on other examples of how to create arrays of generic type parameters it seems like something like the following code should work, but ultimately it fails only at the return of the function where the Object[][]
cannot be cast to an Integer[][]
. It would fail earlier except that IIRC the initial cast of (T[][])
is basically removed at compile time and acts to prevent a warning, thus it has no real impact.
@SuppressWarnings("unchecked")
public static <T> T[][] toTwoDim(T[] array){
int halflen = array.length / 2;
T[][] foo = (T[][]) new Object[2][];
foo[0] = (T[]) new Object[halflen];
foo[1] = (T[]) new Object[halflen];
for(int i = 0; i < halflen; i++){
foo[0][i] = array[i];
foo[1][i] = array[i+halflen];
}
System.out.println(Arrays.asList(foo[0]));
System.out.println(Arrays.asList(foo[1]));
return foo;
}
public static void main(String[] a){
Integer[] bar = {1,2,3,4};
Integer[][] foo = toTwoDim(bar);
System.out.println(Arrays.asList(foo[0]));
}
Upvotes: 1