skip to content

Generic Methods and Constructors

A method can declare its own type parameters before the return type, independent of the class, and the compiler usually infers the arguments at the call site. Knowing the explicit type-witness syntax for when inference fails is the follow-up.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

How do you declare a generic method in Java, and where does the type-parameter section go?

level: juniorimportance: must knowfreq 78%

answer

  1. Type params go before the return type
  2. `<T>` after modifiers, before return type
  3. Method owns its own type variable
  4. Even non-generic classes can have generic methods
  5. Conventional names: T, E, K, V, R

basics

~20 s

You put the type parameters in angle brackets right before the return type, e.g. static <T> T pick(T a, T b). That <T> introduces a name you can then use for the parameters and return type.

solid answer

~40 s

A generic method declares its own type parameters in an angle-bracket section placed immediately before the return type (and after any modifiers): `public static <T> List<T> wrap(T item)`. The `<T>` introduces a type variable scoped to that single method; you then use `T` in the parameter types, return type, and body. This is independent of whether the enclosing class is generic — even a non-generic class can have generic methods. Multiple parameters are comma-separated (`<K, V>`), and they can have bounds (`<T extends Comparable<T>>`). The compiler usually infers the actual types from the arguments at the call site, so callers rarely write the type explicitly. Static methods especially need their own type parameters because they cannot use the class's type parameters.

code

java · 7 lines
java
public class Util { // not a generic class
    public static <T> T firstOrNull(List<T> list) {
        return list.isEmpty() ? null : list.get(0);
    }
}

String s = Util.firstOrNull(List.of("a", "b")); // T inferred as String

go deeper

for a junior

Can write <T> in the right place and use it in parameters/return; knows the conventional names.

for a middle

Distinguishes a method's type parameter from a class's; adds bounds and multiple type parameters correctly.

for a senior

Explains scoping, when static methods require their own type parameters, and how bounds enable calling methods on the type variable.

for a principal

Frames generic methods as the API tool for expressing relationships between argument and return types without polluting the class signature; guides team conventions.

## What a generic method is A **generic method** is a method that declares one or more **type parameters** (also called *type variables*) of its own. A type parameter is a placeholder name — conventionally a single uppercase letter like `T` (Type), `E` (Element), `K`/`V` (Key/Value), `R` (Result) — that stands for some type the caller will supply or the compiler will figure out. ## The syntax and where the section goes The type-parameter section is a comma-separated list inside angle brackets `< >`. For a **method**, it goes in a specific spot: after the modifiers (`public`, `static`, etc.) and **immediately before the return type**. ``` [modifiers] <TypeParams> ReturnType methodName(params) { ... } ``` Example: ```java public static <T> T firstOrNull(List<T> list) { return list.isEmpty() ? null : list.get(0); } ``` Here `<T>` is the declaration that *introduces* the name `T`. After that point, `T` can be used anywhere in the method's signature (parameter types, return type) and its body. ## Why this differs from a generic class A **generic class** declares its type parameter once, next to the class name: `class Box<T> { ... }`. Every instance method of `Box` can then freely use `T` — it belongs to the instance. A **generic method** instead owns its type parameter for the duration of a single call. The two are independent: - A non-generic class can contain generic methods (the `Collections` utility class is full of them). - A generic class can contain methods that introduce *additional* type parameters beyond the class's own. ## Several type parameters and bounds You can declare more than one: `<K, V>`. You can also constrain a type parameter with a **bound** using `extends`: `<T extends Number>` means *T must be Number or a subtype*. Bounds let the body call methods of the bound type (e.g. `<T extends Comparable<T>>` lets you call `a.compareTo(b)`). ## How the actual type is chosen At the call site the compiler performs **type inference**: it looks at the argument types (and sometimes the target/return context) and deduces what `T` must be. So `firstOrNull(List.of("a", "b"))` infers `T = String`. You can also supply the type explicitly with a *type witness* (covered separately): `Util.<String>firstOrNull(list)`. ## Mental model Think of `<T>` before the return type as a tiny local declaration: 'for the length of this one method call, let `T` mean whatever type fits.' That is why it sits right where it does — it must be introduced before it is first used, and the return type is the first place it appears.

  • Can a generic method appear in a non-generic class?
    Yes. The method declares its own type parameter, independent of the class. `java.util.Collections` (a non-generic utility class) is full of generic methods like `<T> emptyList()`.
  • What does a bound like `<T extends Number>` give you inside the body?
    It lets you treat `T` as a `Number`, so you can call `Number` methods (e.g. `intValue()`) on values of type `T`, and only types that are `Number` or subtypes can be used.

saying these in an interview costs you the question

  • Thinking the `<T>` goes after the method name or in the parameter list
  • Believing only generic classes can have generic methods
  • Confusing the method's `<T>` with a class-level `<T>` — they are separate scopes
  • Saying you must always write the type explicitly at the call site

context

open as a page

What is type-argument inference at a call site, and when do you need an explicit type witness?

level: middleimportance: must knowfreq 62%

basics

~20 s

The compiler usually figures out the type from the arguments, so you just call the method normally. When it can't (e.g. no arguments to look at), you write the type explicitly before the method name, like Collections.<String>emptyList().

open as a page

What is a generic constructor, and how are its type parameters independent of the enclosing class's?

level: seniorimportance: should knowfreq 34%

basics

~20 s

A constructor can declare its own type parameters in angle brackets before the constructor name, separate from the class's type parameters. So even a class that isn't generic can have a constructor that takes a generic argument.

open as a page

When should you use a generic method with a type parameter instead of a method that takes a wildcard argument?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Use a named type parameter (<T>) when you need to relate two things — like returning the same type you receive, or linking two arguments. Use a wildcard (?) when you only consume the argument and don't need to name its type anywhere else.

open as a page

How does type erasure affect generic methods, and why can a static generic method declare its own type parameter while a static field cannot use the class's?

level: principalimportance: should knowfreq 28%

basics

~20 s

Java removes generic type info at compile time (erasure), so at runtime a generic method's T is just Object (or its bound). A static method can declare its own <T> because that type is per-call, but a static field can't use the class's <T> because static members aren't tied to any instance's type.

open as a page