Generics
Generics let classes, interfaces and methods work with any data type while keeping type safety. The type is given as a parameter, written in angle brackets, so one List<T> class can hold strings, numbers or customers, and the compiler checks that only the right type goes in.
Without generics, collections stored plain Object values that had to be cast back, and mistakes only showed up at run time. Generics are found in Java, C#, TypeScript, Kotlin, Go and Rust; C++ achieves the same with templates. Bounded types, such as <T extends Comparable<T>>, limit which types are allowed.
static <T extends Comparable<T>> T max(List<T> items) {
T best = items.get(0);
for (T item : items) if (item.compareTo(best) > 0) best = item;
return best;
}
max(List.of(3, 9, 4)); // 9
max(List.of("pear", "apple")); // "pear"
