Memra

Why generics: type safety and the diamond operator

How generics replaced raw types — type-checked at compile time, zero runtime cost.

The problem generics solve

Before Java 5, collections held Object references. You had to cast on every read, and a wrong cast compiles silently but blows up at runtime:

// Raw type — pre-generics style (avoid this)
List names = new ArrayList();
names.add("Alice");
names.add(42);                  // compiles — no type check!
String s = (String) names.get(1); // ClassCastException at runtime

Generics bind a type parameter to a collection so the compiler enforces the constraint:

List<String> names = new ArrayList<String>();
names.add("Alice");
// names.add(42); // compile error — int is not String
String s = names.get(0);   // no cast needed

The diamond operator <> (Java 7+) lets the compiler infer the type argument from the declared type, so you don't repeat yourself:

List<String>         names  = new ArrayList<>();  // diamond: infers String
Map<String, Integer> counts = new HashMap<>();    // infers both params

Generics are compile-time only: the bytecode has no type arguments (this is called *type erasure*, covered at the end of this module). At runtime both List<String> and List<Integer> are just List.

NORMAL ~/memra/learn/java-from-zero/why-generics utf-8 LF