Skip to content
AgileLogics
5 min read

Advanced Generics & Bounded Type Parameters

Prerequisites: Level 2 — Intermediate

A bounded type parameter restricts what a generic can be substituted with, so the compiler knows more about it — enough to call methods on it directly.

static <T extends Comparable<T>> T max(List<T> list) {
    T result = list.get(0);
    for (T item : list) {
        if (item.compareTo(result) > 0) {
            result = item;
        }
    }
    return result;
}

Wildcards describe a generic whose exact type parameter doesn't matter, only its relationship to a bound:

static double sumAll(List<? extends Number> numbers) {
    double total = 0;
    for (Number n : numbers) {
        total += n.doubleValue();
    }
    return total;
}

sumAll(List.of(1, 2, 3));       // works — List<Integer>
sumAll(List.of(1.5, 2.5));      // works — List<Double>

Common mistakes

  • Using an unbounded <T> and then trying to call a method (like .compareTo()) that only exists on some types — the compiler rejects it because plain T could be anything.