List l = new ArrayList<Number>();
List<String> ls = l; // unchecked warning
l.add(0, new Integer(42)); // another unchecked warning
String s = ls.get(0); // ClassCastException is thrown
The java documentation says;
Furthermore, a heap pollution situation occurs when the l.add method
is called. The static type second formal parameter of the add method
is String, but this method is called with an actual parameter of a
different type, Integer. However, the compiler still allows this
method call. Because of type erasure, the type of the second formal
parameter of the add method (which is defined as List.add(int,E))
becomes Object. Consequently, the compiler allows this method call
because, after type erasure, the l.add method can add any object of
type Object, including an object of Integer type
my question is about the part i made bold. I understand that in line 2 heap pollution occurs cause l being of List references an object of type List. But when add method is called on l reference shouldn’t it expect Number type instead of String as l is reference to ArrayList. Or is it, that after ls=l the space in heap is made of List<String> also for the l reference? in this case makes sense what java docs says in the part made in bold
List lis just declared as an untyped List. So the compiler will let you put in whatever you like (and warn about it), and let you assign it to an incompatibleList<String>variable (and warn about it).If you said
List<Number> l, the compiler would enforce the proper types (and not let you assign it tols).No matter what generic types you declare or not declare, this has no effect at runtime. To maintain backwards compatibility, generics are a complete compile-time-only feature.
If you say
you have four different variables (with four different type declarations), but they all point to the same data (the same object on the heap).