Generics
Generic Classes & Methods
Declare type parameters on classes (
class Box<T>) or individual methods (static <T> T pick(...)). The compiler infers method type arguments from the call — you rarely spell them out.- Class-level parameter:
class Pair<T>— one type variable for the whole instance - Method-level parameter:
<T>before the return type; independent per call - Type arguments are inferred:
Pair.of("a", 1)figures outPair<String,Integer> - Conventions:
Ttype,Eelement,K/Vkey/value,Rresult - Favor generic types and methods over Object-based ones (EJ 29–30)
public class Pair<T> {
private final T first;
private final T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() { return first; }
public T getSecond() { return second; }
}public static <T> T getMiddle(T... a) {
return a[a.length / 2];
}
String mid = getMiddle("John", "Q.", "Public"); // T inferred as StringInference occasionally surprises: getMiddle("Hello", 0, null) infers the common supertype of String and Integer — a legal but unintended Object-ish type. When inference goes sideways, pass explicit type arguments: Collections.<String>emptyList().
Generic records work too: record Pair<T>(T first, T second) {} — one line replaces the class above (see Records). Generic constructors infer through the diamond: new HashMap<String, List<Integer>>() is just new HashMap<>() in assignment context.