Under Construction

This guideline is under construction. 

Mixing generically typed code with raw typed code is one common source of heap pollution. Prior to Java 5, all code used raw types. Allowing mixing enabled developers to preserve compatibility between non-generic legacy code and newer generic code. Using raw types with generic code causes most Java compilers to issue "unchecked" warnings but still compile the code. When generic and nongeneric types are used together correctly, these warnings can be ignored; at other times, these warnings can denote potentially unsafe operations.

According to the Java Language Specification§4.8, "Raw Types," [JLS 2005]:

The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of genericity into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.

Noncompliant Code Example

This noncompliant code example compiles but results in heap pollution.  The compiler produces an unchecked warning because a raw argument (the obj parameter in the addToList() method) is passed to the List.add() method. 

class ListUtility {
  private static void addToList(List list, Object obj) {
    list.add(obj); // unchecked warning
  }

  public static void main(String[] args) {
    List<String> list = new ArrayList<String> ();
    addToList(list, 42);
    System.out.println(list.get(0));  // throws ClassCastException
  }
}

Heap pollution is possible in this case because the parameterized type information is discarded prior to execution.  The call to addToList(list, 42) succeeds in adding an integer to list although it is of type List<String>.  This Java runtime does not throw a ClassCastException until the value is read and has an invalid type (an int rather than a String). In other words, the code throws an exception some time after the execution of the operation that actually caused the error, complicating debugging.

Even when heap pollution occurs, the variable is still guaranteed to refer to a subclass or subinterface of the declared type, but is not guaranteed to always refer to a subtype of its declared type.  In this example, list does not refer to a subtype of its declared type (List<String>), but only to the subinterface of the declared type (List).

Compliant Solution (Parameterized Collection)

This compliant solution enforces type safety by changing the addToList() method signature to enforce proper type checking.

class ListUtility {
  private static void addToList(List<String> list, String str) {
    list.add(str);     // No warning generated
  }

  public static void main(String[] args) {
    List<String> list = new ArrayList<String> ();
    addToList(list, "42");
    System.out.println(list.get(0));
  }
}

The compiler prevents insertion of an Object to the parameterized list because addToList() cannot be called with an argument whose type produces a mismatch. This code has consequently been changed to add a String to the list instead of an int.