skip to content

A static method needs to operate on a type parameter, but it can't use the enclosing class's T. How do you write it correctly, and what is different about that type parameter?

level: middleimportance: should knowfreq 45%

answer

  1. Own <U> goes before the return type
  2. Class T = per object; method U = per call
  3. Collections.emptyList / Arrays.asList are the proof
  4. Method param shadows class T if same letter
  5. Call-site inference picks U

basics

~10 s

Give the static method its own type parameter, like static <U> U pick(U x). That U is decided each time you call the method, not per object, so it doesn't clash with the rule.

solid answer

~50 s

The restriction only blocks using the *class's* type parameter (the one tied to instances) in a static context. A static method may still be generic — you declare a fresh type parameter on the method itself, written before the return type: `static <U> U firstOrNull(List<U> list)`. That `U` is bound at each *call site* from the arguments (or an explicit `Box.<String>firstOrNull(...)`), so it never depends on any instance. This is why utility methods like `Collections.emptyList()` (`static <T> List<T> emptyList()`) and `Arrays.asList` work as statics. Key distinction: a class type parameter is fixed when an object is constructed and shared by that object's instance members; a method type parameter is fixed when the method is invoked and exists only for that call. The method's parameter may even reuse the letter `T`, but it is a *different, independent* `T` that shadows the class's.

code

java · 14 lines
java
class Box<T> {
    private T value;

    // Wrong: uses the class's T in a static method
    // static T unwrap(Box<T> b) { return b.value; }

    // Right: the static method declares its OWN type parameter U
    static <U> U unwrap(Box<U> b) {
        return b.value;
    }
}

// Call site infers U:
// String s = Box.unwrap(new Box<String>());

go deeper

for a junior

Knows the recipe: add <U> before the return type to make a static method generic.

for a middle

Explains the per-call vs per-instance distinction and cites JDK examples like Collections.emptyList.

for a senior

Discusses inference, explicit type witnesses (Cls.<T>m()), bounds on method parameters, and the shadowing pitfall of reusing the class letter.

for a principal

Can reason about overload resolution / inference interactions and when an explicit type argument is required to disambiguate.

## Background terms - **Type parameter**: a placeholder type. A *class* can declare them (`class Box<T>`) and so can an individual *method* (`<U> U pick(U x)`). - **Class type parameter** (`T` on `Box<T>`): chosen when you build an object — `new Box<String>()`. It is in scope for all *instance* members and is conceptually 'owned' by the object. - **Method type parameter** (`U` on a generic method): chosen when you *call* the method, inferred from the arguments or given explicitly. It is owned by the *invocation*, not by any object. - **Static method**: belongs to the class, callable without an instance (`Box.pick(...)`). ## The rule restated You may not use the **class's** type parameter in a static context, because that parameter is per-instance and a static member is per-class (one shared slot, many instance-specific meanings). See the companion question for the full contradiction. But this rule is *narrow*: it forbids only the **class-owned** parameter. A static method is free to introduce its **own** type parameter, because that one is resolved per call and never needs any instance. ## How to write the generic static method Declare the type parameter list *immediately before the return type*: ```java static <U> U firstOrNull(List<U> list) { return list.isEmpty() ? null : list.get(0); } ``` - `<U>` after `static` introduces a brand-new type parameter scoped to this method only. - `U` is then usable in the parameter types, the return type, and the body. - At the call site the compiler **infers** `U`: `String s = firstOrNull(List.of("a"));` infers `U = String`. You can also force it: `Box.<String>firstOrNull(...)`. ## Why this is allowed when `static T` is not | Aspect | Class param `T` | Method param `U` | |---|---|---| | Chosen when | object is constructed | method is called | | Owned by | the instance | the single invocation | | Needs an instance? | yes | no | | Legal in a static member? | **no** | **yes** | Because `U` is created and destroyed within one call and requires no object, it coexists perfectly with `static` (which also requires no object). ## Real-world proof The JDK is full of these: - `Collections.emptyList()` → `public static final <T> List<T> emptyList()` - `Arrays.asList(T... a)` → `public static <T> List<T> asList(T... a)` - `Optional.of(T value)` → `public static <T> Optional<T> of(T value)` Each declares its **own** `<T>` even though the surrounding class isn't generic — proving the `<T>` belongs to the method. ## Shadowing gotcha Inside a generic class you can write `static <T> T id(T x)`. That method-level `T` is a *different* type from the class's `T` and **shadows** it inside the method. This compiles, but reusing the same letter is confusing — pick a distinct letter (e.g. `U`) for clarity. ## Bounds and multiple parameters Method type parameters can be bounded and multiple, just like class ones: `static <K extends Comparable<K>, V> K maxKey(Map<K, V> m)`. ## Summary Don't reach for the class's `T` in a static method — give the method its own type parameter. It's the standard, idiomatic way and is exactly how the JDK's static factory and utility methods are built.

  • Where exactly does the method's type-parameter list go?
    Between the modifiers and the return type: `public static <U> U pick(...)`. It introduces U for use in the parameters, return type, and body.
  • Can the method's type parameter be named T, the same as the class's?
    Yes, syntactically — it shadows the class's T inside the method and is a distinct, independent type. It compiles but is confusing; prefer a different letter.
  • How does the compiler know what U is at a call?
    Type inference from the argument types (and the assignment/target type), or you can specify it explicitly with `ClassName.<Type>method(...)`.

saying these in an interview costs you the question

  • Thinking you must make the whole class non-generic to have a generic static method — the method just needs its own parameter.
  • Believing static methods can't be generic at all.
  • Placing the `<U>` in the wrong spot (it goes before the return type, not after the method name).

context