Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Generically typed code can be freely used with raw types when attempting to preserve compatibility between non-generic legacy code and newer generic code. However, using raw types with generic code cause causes most Java compilers to issue "unchecked" warnings. When generic and non-generic types are used together correctly, these warnings are not catastrophic, but at other times, these warnings may denote potentially unsafe operations. If generic and non-generic code must be used together, these warnings should not be simply ignored.

...

Code Block
List l = new ArrayList<Integer>();
List<String> ls = l; // producesProduces unchecked warning

However, to implement this guideline unchecked warnings cannot not be relied upon. According to the Java Language Specification [JLS 05] section 4.12.2.1 "Heap Pollution":

...

Noncompliant Code Example

This noncompliant code example produces an unchecked warning because the raw type of the List.add() method is used (the list parameter in addToList() method) instead of the parameterized type. To make this code compile cleanly, the @SuppressWarnings annotation is used.

Code Block
bgColor#FFCCCC
public class MixedTypes {
  @SuppressWarnings("unchecked")
  private static void addToList(List list, Object obj) {
    list.add(obj);     // "unchecked"Unchecked warning
  }
  private static void print() {
    List<String> list = new ArrayList<String> ();
    addToList(list, 1);
    System.out.println(list.get(0));
  }
  public static void main(String[] args) {
    MixedTypes.print();
  }
}

...

Code Block
bgColor#ccccff
class Parameterized {
  private static void addToList(List<String> list, String str) {
    list.add(str);     // "unchecked"Unchecked warning
  }
  private static void print() {
    List<String> list = new ArrayList<String> ();
    addToList(list, "1");
    System.out.println(list.get(0));
  }
  public static void main(String[] args) {
    Parameterized.print();
  }
}

Noncompliant Code Example

This noncompliant code example suffers from related pitfalls. It compiles and runs cleanly. The method printOne is intended () intends to print the value one, either as an int or as a double depending on the type of the variable type. However, despite list being correctly parameterized, this method always print '1' and never '1.0' because the int value '1' is always added to list without being type checked.

Code Block
bgColor#FFCCCC
class BadListAdder {
  @SuppressWarnings("unchecked")
  private static void addToList(List list, Object obj) {
    list.add(obj);     // "unchecked"Unchecked warning
  }
  private static <T> void printOne(T type) {
    if (!(type instanceof Integer || type instanceof Double)) {
      System.out.println("Cannot print in the supplied type");
    }
    List<T> list = new ArrayList<T> ();
    addToList(list, 1);
    System.out.println(list.get(0));
  }
  public static void main(String[] args) {
    double d = 1;
    int i = 1;
    System.out.println(d); 
    BadListAdder.printOne(d);
    System.out.println(i);
    BadListAdder.printOne(i);
  }
}

...

Code Block
bgColor#ccccff
class GoodListAdder {
  private static void addToList(List<Integer> list, Integer i) {
    list.add(i);
  }
  private static void addToList(List<Double> list, Double d) {
    list.add(d);
  }
  private static <T> void printOne(T type) {
    if (type instanceof Integer) {
      List<Integer> list = new ArrayList<Integer> ();
      addToList(list, 1);
      System.out.println(list.get(0));
    }
    else if (type instanceof Double) {
      List<Double> list = new ArrayList<Double> ();

      // This will not compile if addToList(list, 1) is used
      addToList(list, 1.0);

      System.out.println(list.get(0));
    }
    else {
      System.out.println("Cannot print in the supplied type");
    }
  }
  public static void main(String[] args) {
    double d = 1;
    int i = 1;
    System.out.println(d);
    GoodListAdder.printOne(d);
    System.out.println(i);
    GoodListAdder.printOne(i);
  }
}

...