tags:

views:

150

answers:

2

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 :-)

+3  A: 

The general idea is that all type-related information is erased if you use raw version of parameterized type. That includes either type information implied by class type parameters or generic methods parameters as well.

Very similar example is described here.

denis.zhdanov
Adding a summary of your blog post would be nice for future visitors.
kdgregory
Can't read your blog from work so this is a non-answer (without a summary).
Bob Cross
Thanks for that. Any idea *why* this rule is enforced? (Especially when the declaration on the class is completely orthogonal to the method declaration ...)
alasdairg
No :( The only ideas are:* to help javac developers;* enforce developers to avoid using raw classes;
denis.zhdanov
A: 

I've come across this before but explaining it might cause you further confusion so I'm linking you to the JLS section on "Raw Types" which you can read to fully understand what's going on then you can come back with further questions if you don't get it.

non sequitor