OK - I know that Java generics can be a minefield for the unwary, but I just came across a non-intuitive (to me anyway) behavior that I was wondering if anyone can explain: First of all, here's a class that compiles:
public class Dummy {
public List<? extends Number> getList() {
return new ArrayList<Number>();
}
public static void main(String[] args) {
Dummy dummy = new Dummy();
for (Number n: dummy.getList()) {
System.out.println(n);
}
}
}
Simple stuff. Now, I make a single change by adding a type parameter T to Dummy:
public class Dummy<T> {
Now the class fails to compile, giving the error "Type mismatch: cannot convert from element type Object to Number" on the for() statement
It appears that because I have parameterized the Dummy class, the creation of the new Dummy() in the main method (without specifying a type parameter), causes the type information for the getList() method to no longer be available: The compiler no longer knows the type of the list elements, so they can't be assigned to a loop variable of type Number. Why does this type information go missing, given that the <T> declaration on the class has nothing at all to do with the <? extends Number> declaration on the getList() method?
Furthermore, if I now change my instantiation of Dummy to be:
Dummy<?> dummy = new Dummy();
Then the type information becomes available again, and the class compiles once more. So why is a "Dummy of unknown type" allowed to retain its getList() type information whilst a Dummy (presumably of unknown type since I didn't specify a parameter) loses it?
Maybe I'm the Dummy :-)