Why Generics

The Problem Without Generics

Before Java 5, collections stored Object. You could put anything in, and had to cast when taking things out. Mistakes appeared only at runtime as ClassCastException.

Example

import java.util.ArrayList;
import java.util.List;

public class Main {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        List raw = new ArrayList();          // raw type: no type checking
        raw.add("Asha");
        raw.add(42);                         // compiler does not complain
        for (Object o : raw) {
            try {
                String s = (String) o;
                System.out.println("Name: " + s);
            } catch (ClassCastException e) {
                System.out.println("Crash at runtime for value " + o);
            }
        }

        List<String> names = new ArrayList<>();   // generic: checked at compile time
        names.add("Ravi");
        // names.add(42);                    // compile error: incompatible types
        String first = names.get(0);         // no cast needed
        System.out.println("Generic list gives: " + first);
    }
}

Output

Name: Asha
Crash at runtime for value 42
Generic list gives: Ravi

Benefits

  • Type safety: wrong types are caught by the compiler.
  • No casts: list.get(0) already has the right type.
  • Reusable code: write Box<T> once, use it for any type.
LetterConvention
TType
EElement (collections)
K, VKey, Value (maps)
RReturn type
NNumber