As mentioned
earlier, arrays in Java are covariant. This means you can reference an object of type
String[]
through a variable of type
Object[]
and, for example, insert an
Integer
into it. Such code will compile, but when you try to store the value, an
ArrayStoreException
will be thrown.
Generics are protected by invariance. If you try to assign a
List<String>
value into a
List<Object>
variable, this type of error occurs already at compile time.
Heap pollution occurs when this protection fails, and a variable of a parameterized type holds an object parameterized with a different type. A simple example:
List<String> strings = (List) new ArrayList<Integer>();
The documentation
guarantees that if the entire code is compiled
together, heap pollution cannot happen without a compile-time warning.
Heap pollution can occur in two cases: when using arrays of generics and when mixing parameterized and raw types.
Raw types are parameterized types without specifying the parameter. An example with raw types that leads to heap pollution was already described above. Raw types should generally be avoided; the reasons are thoroughly explained in Chapter 26 of
Effective Java. If information about generics is not needed, the wildcard (<?>) should be used instead.
The compiler does not allow the creation of arrays of parameterized types, as this would cause a
"generic array creation" error. The illustration below shows what could happen in such cases.
A parameterized type of varargs argument of a method causes the same problem, as varargs are essentially array parameters. This is why it also triggers the "possible heap pollution" compiler warning. If you are sure there is no risk, starting from Java 7, this warning can be suppressed with the
@SafeVarargs
annotation.