Java Tutorial · Advanced Java · Lesson 30 of 37
Java Generics
Write type-safe classes and methods that work with any type.
Why generics?
Generics let a class or method work with any type while keeping compile-time type checking. List<String> can only hold strings — no casts, no surprises at runtime.
Generic classes
public class Main {
public static void main(String[] args) {
Box<String> name = new Box<>("Ada");
Box<Integer> count = new Box<>(42);
System.out.println(name.get().toUpperCase() + " " + (count.get() + 1));
Pair<String, Double> price = new Pair<>("coffee", 3.5);
System.out.println(price);
}
}
class Box<T> {
private final T value;
Box(T value) { this.value = value; }
T get() { return value; }
}
record Pair<A, B>(A first, B second) {}
Output
ADA 43 Pair[first=coffee, second=3.5]
Run this on your computer — see “Get Started” for setup.
Generic methods and bounds
A type parameter can be bounded: <T extends Comparable<T>> means "any T that can be compared":
import java.util.List;
public class Main {
public static void main(String[] args) {
System.out.println(max(List.of(3, 9, 4)));
System.out.println(max(List.of("pear", "apple", "zucchini")));
System.out.println(sum(List.of(1, 2, 3)) + " " + sum(List.of(1.5, 2.5)));
}
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;
}
static double sum(List<? extends Number> numbers) {
double total = 0;
for (Number n : numbers) total += n.doubleValue();
return total;
}
}
Output
9 zucchini 6.0 4.0
Run this on your computer — see “Get Started” for setup.
Wildcards: List<? extends Number> accepts lists of Integer, Double… for reading; List<? super Integer> for writing. Remember PECS — Producer Extends, Consumer Super.
Test yourself
What does <T extends Comparable<T>> mean?
T must be a subclass of ComparableT must be a type that can be compared to itselfT can be any typeT must be a number
Show answer
Answer: T must be a type that can be compared to itself