Type Parameters in Java Generics β <code><T></code>
A type parameter is a placeholder for a concrete type that the compiler fills in at each use site. <T> in List<T> is what makes List<String> and List<Integer> different types. Type parameters exist on classes, interfaces, and methods.
Generic class
public class Box<T> {
private final T value;
public Box(T value) { this.value = value; }
public T get() { return value; }
}
Box<String> s = new Box<>("hello"); // diamond infers <String>
Box<Integer> i = new Box<>(42);
Generic method
public static <T> List<T> repeat(T value, int n) {
List<T> out = new ArrayList<>();
for (int k = 0; k < n; k++) out.add(value);
return out;
}
var words = repeat("hi", 3); // List<String> β inferred
var nums = Utils.<Integer>repeat(0, 5); // explicit type witness β rarely needed
The <T> before the return type declares the type parameter. It's local to the method β not tied to the enclosing class's type parameters.
Multiple type parameters
public record Pair<A, B>(A first, B second) {}
public static <K, V> Map<V, K> invert(Map<K, V> in) {
var out = new HashMap<V, K>();
in.forEach((k, v) -> out.put(v, k));
return out;
}
Naming conventions
| Letter | Typical meaning |
|---|---|
T | Type (single) |
E | Element of a collection |
K, V | Key, Value (for maps) |
R | Return type |
N | Number |
For domain-specific generics, spell it out: <Event>, <Payload>. No one-letter law.
Type inference rules (simplified)
- Diamond (
<>): inferred from the left-hand side. - Method call: inferred from the argument types and the expected return type (target typing).
var: inferred from the initialiser.
Bounded type parameters (preview)
public static <T extends Comparable<T>> T max(List<T> xs) { ... }
See the bounded types page for the full treatment.
Common mistakes
- Declaring
<T>twice β once on the class and once on a method in the class with the same name. The method'sTshadows the class's. - Using a raw type β
List list = new ArrayList(). Always parameterise. - Over-genericising β if every type is
<T>, the abstraction no longer says anything about the domain.
Related
Pillar: Java generics. See also wildcards, bounded types.