Bounded Type Parameters in Java β <code><T extends ...></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
implementsinstead ofextendsβ wrong; alwaysextendsin 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 compareTagainstTsafely.
Related
Pillar: Java generics. See also wildcards, type parameters.