The reason for these limitations have to do with variance considerations.
Take the following code:
public void doSomething(List<Object> objects)
{
objects.add(new Object());
}
Expanding your example, you could try to do the following:
List<String> strings = new ArrayList<String>();
string.add("S1");
doSomething(strings);
for (String s : strings)
{
System.out.println(s.length);
}
Hopefully it's obvious why this would break if the compiler allowed this code to be compiled (which it doesn't) - a ClassCastException
would occur for the second item in the list when trying to cast the Object
to a String
.
To be able to pass generalized collection types, you need to do this:
public void doSomething(List<?> objects)
{
for (Object obj : objects)
{
System.out.println(obj.toString);
}
}
Again, the compiler is watching your back and were you to replace the System.out
with objects.add(new Object())
the compiler wouldn't allow this because objects
could have been created as List<String>
.
For more background on Variance see the Wikipedia artical Covariance and contravariance