I came across something very basic but extremely bewildering today. I needed to convert a list to an array. The list contained String
instances. Perfect example of using List.toArray(T[])
, since I wanted a String[]
instance. It would not work, however, without explicitly casting the result to String[]
.
As a test scenario, I used the following code:
import java.util.Arrays;
import java.util.List;
public class MainClass {
public static void main(String args[]) {
List l = Arrays.asList("a", "b", "c");
String stuff[] = l.toArray(new String[0]);
System.err.println(Arrays.asList(stuff));
}
}
which does not compile. It's nearly an exact copy of the example in the javadoc, yet the compiler says the following:
MainClass.java:7: incompatible types
found : java.lang.Object[]
required: java.lang.String[]
String stuff[] = l.toArray(new String[0]);
^
If I add a cast to String[]
it will compile AND run perfectly. But that is not what I expect when I looked at the signature of the toArray method:
<T> T[] toArray(T[] a)
This tells me that I shouldn't have to cast. What is going on?
Edit:
Curiously, if I change the list declaration to:
List<?> l = Arrays.asList("a", "b", "c");
it also works. Or List<Object>
. So it doesn't have to be a List<String>
as was suggested. I am beginning to think that using the raw List
type also changes how generic methods inside that class work.
Second edit:
I think I get it now. What Tom Hawtin wrote in a comment below seems to be the best explanation. If you use a generic type in the raw way, all generics information from that instance will be erased by the compiler.