In the Java tutorials ( http://docs.oracle.com/javase/tutorial/extra/generics/fineprint.html ) I saw the following:
// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;
// Run-time error: ClassCastException.
String s = lsa[1].get(0);
If arrays of parameterized type were allowed, the previous example
would compile without any unchecked warnings, and yet fail at run-time
// OK, array of unbounded wildcard type.
List<?>[] lsa = new List<?>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Correct.
oa[1] = li;
// Run time error, but cast is explicit.
String s = (String) lsa[1].get(0);
They then explained that if we switch List<String>[] lsa = new List<String>[10];
to
List<?>[] lsa = new List<?>[10];
then it's okay but we have to upcast.
A proffessor of mine asked the following about this: "Why does the latter compile?"
He then gave the answer: "When the argument is ? the meaning is that every cell in the array can include an ArrayList. Because there aren't any assumptions about the type of the generic class the previous exception can't happen."
It still doesn't really make sense to me that the the wildcard one works while the previous one doesn't. If we had to enforce upcasting in the wildcard example why couldn't we do it in the first example as well?
I'd appreciate if someone could clear this up for me.