Bounded Type Parameters in Java β€” <code>&lt;T extends ...&gt;</code>

A bounded type parameter constrains what types can substitute for it. <T extends Number> means "T must be Number or a subtype". Inside the method, T has all the capabilities of Number.

Single bound

public static <T extends Number> double sum(List<T> xs) {
    double total = 0;
    for (T x : xs) total += x.doubleValue();    // safe β€” T extends Number
    return total;
}

sum(List.<Integer>of(1, 2, 3));   // βœ…
sum(List.<Double>of(1.0, 2.0));   // βœ…
sum(List.<String>of("a"));         // ❌ String is not a Number

extends even for interfaces

public static <T extends Comparable<T>> T max(List<T> xs) {
    T best = xs.get(0);
    for (T x : xs) if (x.compareTo(best) > 0) best = x;
    return best;
}

Regardless of whether the bound is a class or an interface, the keyword is extends.

Multiple bounds with &

public static <T extends Number & Comparable<T>> T biggest(List<T> xs) {
    T best = xs.get(0);
    for (T x : xs) if (x.compareTo(best) > 0) best = x;
    return best;
}

If one bound is a class, it must come first. The rest must be interfaces. The type T has every method of every bound.

Bounded wildcards vs bounded type parameters

// Type parameter β€” same T everywhere
public static <T extends Number> void addTo(List<T> dst, T item) { dst.add(item); }

// Wildcard β€” can't know what to add
public static void printAll(List<? extends Number> xs) {
    for (Number n : xs) System.out.println(n);
}

Use a named type parameter when the type appears in multiple positions; use a wildcard when you only need to refer to "some subtype of T" once.

Recursive bounds

public static <T extends Comparable<T>> T max(List<T> xs) { ... }

"T must be comparable to itself" β€” the classic pattern for sortable or orderable types.

Common mistakes

  • Using implements instead of extends β€” wrong; always extends in a bound.
  • Too many bounds β€” if a type parameter needs 4 bounds, you probably want an interface that combines them.
  • Forgetting the recursive bound on Comparable β€” without <T extends Comparable<T>> you can't compare T against T safely.

Related

Pillar: Java generics. See also wildcards, type parameters.