why does List<String>.toArray() return Object[] and not String[]? how to work around this?
You need to pass in an array so its runtime type can be used as a hint by toArray
. Try toArray(new String[0])
instead. You can also pass in a pre-sized array.
To understand, consider what type erasure would have to do to make
new T[4]
work. If Java allowed that, the best it could do post erasure is
new Object[4]
Most toArray
implementations use java.lang.reflect.Array
to construct an output array of the right type given a type hint passed as a Class
.
Because arrays have been in Java since the beginning, while generics were only introduced in Java 5. And the List.toArray()
method was introduced in Java 1.2, before generics existed, and so it was specified to return Object[]
. Lots of existing code now expects List.toArray()
to return Object[]
, so it can't be changed now.
Furthermore, generics are erased at runtime, so ArrayList
couldn't even construct an array of the proper type if it wanted to.
The loophole for this is the List.toArray(T[])
method, which will return you an array of the correct type, provided you give it an array of the correct type so it knows what type to use.
To understand why that happens, just have a look at the javadoc for Collection.toArray()
and then look at the Collection.toArray(T[] a)
method. Also keep in mind that generics in Java are erased at runtime.
The reasons are two:
The method preceded Generics and they couldn't change the signature without breaking backwards compatibility.
In any case, as the
List
is constructed without aClass<T>
there is no way for the implementation to construct an array of typeT
.
Workaround will be to use:
List<String> list = new ArrayList<>();
list.add("Sputnik");
list.add("Explorer");
//String[] str = list.toArray();
This is bound to throw an : incompatible types: Object[] cannot be converted to String[] error
Instead use:
String[] str = list.toArray(new String[0]);
or
String[] str = list.toArray(new String[list.size()]);