Generic methods: declaring and calling
Adding a type parameter to a single method — and how the compiler infers it at the call site.
When only the method needs to be generic
Sometimes you need type safety for one operation without making the whole class generic. A generic method declares its own type parameter in angle brackets before the return type:
public static <T> T firstOrNull(List<T> xs) {
return xs.isEmpty() ? null : xs.get(0);
}
The <T> before T is the declaration; the two Ts that follow are uses. The compiler infers the type at the call site:
List<String> words = List.of("hello", "world");
List<Integer> ints = List.of(1, 2, 3);
String first = firstOrNull(words); // T inferred as String
Integer num = firstOrNull(ints); // T inferred as Integer
You can supply the type argument explicitly when inference fails:
String result = MyUtil.<String>firstOrNull(new ArrayList<>());
Generic methods appear constantly in utility classes (Collections.sort, Arrays.asList, List.copyOf). Recognising the <T> placement before the return type is the key reading skill.