I am doing some tests with generic-methods and I'd like to transform these two methods below (convertFloatListToArray and convertShortListToArray) in just one (convertListToArray):
public class Helper{
public static float[] convertFloatListToArray(List<Float> list){
float[] array = new float[list.size()];
for(int i = 0; i<list.size(); i++){
array[i] = list.get(i);
}
return array;
}
public static short[] convertShortListToArray(List<Short> list){
short[] array = new short[list.size()];
for(int i = 0; i<list.size(); i++){
array[i] = list.get(i);
}
return array;
}
}
But when I try to use generics, as below, I have some errors:
public class Helper{
public static <T, E> T convertListToArray(List<E> list){
T array = new T[list.size()];
for(int i = 0; i<list.size(); i++){
array[i] = list.get(i);
}
return array;
}
}
I can understand java limitations about generics, but I wonder if someone know any solution, using generic-method, that I am not seeing.
As of the current version (Java 12), primitive types can't be represented with Java generics. More specifically, we can't provide a primitive type as a type argument. (We can't do e.g.
Foo<int>
.) We also can't use type variables as the type in anew
expression, so we can't donew T[n]
to create an array. Therefore, there's no ideal way to do this.It is possible to do this reasonably using some reflection (
java.lang.reflect.Array
), but we need to provide aClass
as an argument. Here's an example of how it might be done:Example call:
Note that
Array.set
will perform a widening primitive conversion, so the following works:But it won't perform a narrowing conversion, so the following throws an exception:
If you wanted, that code could also be used to make duplication easier:
(Having multiple methods like that isn't really generic, though.)
One solution that you'll sometimes see places looks something like this:
There are a variety of problems with that, though:
P
, so there's a danger of heap pollution.It's much better to just pass in a
Class
as an argument.Also, while it's possible to just write many overloads which unbox arrays:
Because of the effects of type erasure, it's impossible to write overloads which unbox many different types of
List
, as in the following:That won't compile, because we aren't allowed to have more than one method in the same class with the same name and erasure. The methods would have to have different names.
As a side-note, here are some non-generic solutions:
As of Java 8 we can unbox
List
s ofInteger
,Long
andDouble
using theStream
API:Google Guava has
Collection
unboxing methods in theircom.google.common.primitives
classes, for exampleDoubles.toArray
: