Memra

Generic methods & bounded type parameters

Put <T> on a single method, and constrain it with extends so you can call the methods you need.

A generic method

A method can have its own type parameters, independent of any class. You declare them before the return type, in angle brackets:

public static <T> T firstOrNull(List<T> list) {
    return list.isEmpty() ? null : list.get(0);
}

Read it left to right: <T> introduces the parameter, T is the return type, List<T> is the argument. The compiler infers T from the argument at the call site — you almost never write it explicitly:

List<String> names = List.of("Ann", "Bo");
String s = firstOrNull(names);   // T inferred as String

A generic method does not need a generic class. The static method above lives in an ordinary class; <T> is scoped to that one method.

Why bounds are needed

Inside firstOrNull, the only thing you know about a T is that it is *some* object — so you can only call Object methods (toString, equals, …). To do more, you must bound the type parameter, promising the compiler that T is at least some known type. Use extends (for both classes and interfaces):

public static <T extends Comparable<T>> T max(List<T> list) {
    T best = list.get(0);
    for (T item : list) {
        if (item.compareTo(best) > 0) {   // legal: T IS-A Comparable<T>
            best = item;
        }
    }
    return best;
}

Without the bound, item.compareTo(best) would not compile — Object has no compareTo. <T extends Comparable<T>> tells the compiler 'whatever T is, it implements Comparable<T>', which unlocks the method. Call it on any comparable element type:

Integer m = max(List.of(3, 9, 1));      // 9
String  w = max(List.of("a", "z", "m")); // "z"

Multiple bounds

A parameter can have several bounds joined with &. At most one may be a class and it must come first; the rest are interfaces:

<T extends Number & Comparable<T>> ...

Now T is guaranteed to be a Number *and* Comparable, so you may call methods from both.

NORMAL ~/memra/learn/comp-308/generic-methods-bounded-type-params utf-8 LF