Java Programming Generics Tutorial Study Guide

Java Generics - Complete Tutorial

Master Java Generics: Learn type parameters, generic classes and methods, bounded types, wildcards, type erasure with practical examples and best practices for type-safe code.

1. Introduction to Generics

Generics let you parameterize types so collections and classes enforce type safety at compile time without casting.

  • Type parameters: List
  • Compile-time type checking
  • Eliminates unsafe casts
  • Introduced in Java 5
Generics intro
import java.util.*;

public class GenericsIntro {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Java");
        String first = names.get(0);
        System.out.println(first);
    }
}

2. Generic Classes and Methods

Define your own generic types with type parameters in angle brackets. Generic methods declare type params before the return type.

  • class Box { T value; }
  • Multiple params: Map
  • Generic methods: void print(T item)
  • Cannot use primitives as type args
Generic class
class Pair<K, V> {
    K key;
    V value;
    Pair(K key, V value) { this.key = key; this.value = value; }
}
public class GenericClassDemo {
    public static void main(String[] args) {
        Pair<String, Integer> p = new Pair<>("age", 25);
        System.out.println(p.key + " " + p.value);
    }
}

3. Bounded Type Parameters

Bounds restrict type parameters to subclasses of a class or implementors of an interface using extends.

  • limits to Number subclasses
  • Multiple bounds: T extends A & B
  • Wildcards: ? extends Number
  • ? super Integer for lower bound
Bounded generic
class NumberBox<T extends Number> {
    T value;
    NumberBox(T value) { this.value = value; }
    double doubleValue() { return value.doubleValue(); }
}

4. Type Erasure

Java removes generic type information at compile time for backward compatibility. At runtime, List becomes raw List.

  • Generics are compile-time feature
  • Runtime cannot use new T()
  • instanceof with generics limited
  • Bridge methods preserve polymorphism
Erasure awareness
import java.util.*;

public class ErasureDemo {
    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
        List<Integer> ints = new ArrayList<>();
        System.out.println(strings.getClass() == ints.getClass());
    }
}

5. Practical Generics Examples

Generics appear in repositories, API responses, and reusable data structures throughout enterprise Java.

  • Generic repository interface
  • Response wrapper Response
  • Utility method Collections.max with Comparable
  • EnumMap and EnumSet type-safe enums
Generic method
public class GenericUtil {
    static <T> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

6. Generics Best Practices

Use generics everywhere instead of raw types. Prefer bounded wildcards for flexible APIs.

  • Never use raw types in new code
  • PECS: Producer extends, Consumer super
  • Avoid generic arrays creation
  • Use @SuppressWarnings sparingly
  • Name type params meaningfully: T, E, K, V