//
Generic Programming allows you to write a single class or function that works with multiple data types, determined at compile time. Instead of writing separate IntList, StringList, and DoubleList classes, you write one List<T> that works with any type T.
// Without Generics (uses raw Object — unsafe)
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); // Manual cast — can throw ClassCastException at runtime
// With Generics (type-safe)
List<String> list = new ArrayList<>();
list.add("hello");
String s = list.get(0); // No cast needed. Compiler enforces type safety.
list.add(42); // COMPILE ERROR — caught before the program runs
class Pair<T, U> {
T first;
U second;
Pair(T first, U second) { this.first = first; this.second = second; }
}
Pair<String, Integer> p = new Pair<>("Alice", 30);
static <T extends Comparable<T>> T findMax(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
<T extends Number> restricts T to Number or its subclasses. This allows calling Number methods like intValue() on T.
C++ uses Templates instead of Generics. Templates are resolved at compile time by generating separate code for each type used (monomorphization).
template <typename T>
T findMax(T a, T b) {
return (a > b) ? a : b;
}
findMax(10, 20); // Generates findMax<int>
findMax(3.14, 2.71); // Generates findMax<double>
Java Generics use Type Erasure: generic type information is removed at compile time and replaced with Object (or the bound type). This means you cannot use new T(), instanceof T, or create generic arrays at runtime.