skip to content

What does it mean to declare a function with a `reified` type parameter in Kotlin, and what does it let you do that a normal generic function cannot?

level: juniorimportance: must knowfreq 70%

answer

  1. reified needs inline
  2. Generics erased on JVM -> reified brings type back
  3. Enables value is T, T::class, typeOf<T>()
  4. Body is copied to call site with real type substituted
  5. Replaces passing Class<T> around

basics

~20 s

Marking a generic type with reified (on an inline function) keeps the real type available at runtime. So you can write value is T or T::class, which you normally cannot do because generics are erased.

solid answer

~40 s

On the JVM, generic type arguments are erased at runtime: a normal `fun <T> f()` does not know what `T` is. Kotlin's `inline fun <reified T> f()` works around this. Because the function is `inline`, the compiler copies its body into every call site and substitutes the concrete type for `T`. That makes the type available at runtime, enabling `value is T`, `value as T`, `T::class`, `typeOf<T>()`, and stdlib helpers like `filterIsInstance<T>()`. Constraints: `reified` requires `inline`; you cannot use a reified type from an ordinary (non-inline) function, and you cannot pass a reified `T` where a runtime `Class`/instance is needed unless you reconstruct it (e.g., `T::class.java`). It is the idiomatic replacement for passing `Class<T>` parameters around.

code

kotlin · 5 lines
kotlin
inline fun <reified T> Any?.castOrNull(): T? = this as? T

val x: Any = "hello"
val s: String? = x.castOrNull<String>() // "hello"
val n: Int? = x.castOrNull<Int>()       // null

go deeper

for a junior

Knows reified + inline lets you do value is T and T::class, and that generics are otherwise erased.

for a middle

Explains the inlining mechanism (body copied, type substituted) and why non-inline functions can't reify.

for a senior

Distinguishes T::class (KClass, erased args) from typeOf<T>() (full KType), and frames reified as replacing Class<T> threading.

for a principal

Discusses API design trade-offs: inlining cost/binary size, when a Class<T> parameter is still preferable, and reflection limits.

## The problem: type erasure On the JVM, generics are a compile-time feature. At runtime, the type argument is **erased** — a `List<String>` and a `List<Int>` are both just `List`. So inside a normal generic function you cannot ask "is this value a `T`?" because the bytecode has no record of what `T` was. ```kotlin fun <T> isInstanceOf(value: Any): Boolean { // return value is T // COMPILE ERROR: Cannot check for instance of erased type: T TODO() } ``` ## The solution: `inline` + `reified` If you mark the function `inline` and the type parameter `reified`, the compiler **inlines** the function body at every call site and substitutes the *actual* type argument for `T`. That makes the type physically present in the generated code, so it is **reified** (made real at runtime). ```kotlin inline fun <reified T> isInstanceOf(value: Any): Boolean = value is T isInstanceOf<String>("hi") // compiles to: "hi" is String -> true isInstanceOf<Int>("hi") // compiles to: "hi" is Int -> false ``` ## What `reified` unlocks - `value is T` and `value as T` — runtime type checks and casts. - `T::class` — get the `KClass<T>` (and `T::class.java` for the `Class<T>`). - `typeOf<T>()` — get a full `KType` including generic arguments (e.g. `List<String>`). - Stdlib helpers built this way, e.g. `Iterable<*>.filterIsInstance<T>()`. ## Rules and limits - `reified` **only** works on `inline` functions; it is not allowed on classes or non-inline functions. - You cannot call a `reified` function reflectively, because there is no real function body to invoke — the body only exists inlined at call sites. - It replaces the old Java pattern of threading a `Class<T>` parameter through APIs. Think of `reified` as: "because this function is copy-pasted at the call site, the compiler already knows the concrete type there, so let me use it like a real type."

  • Why can't you mark a normal (non-inline) function's type parameter as reified?
    Because reification depends on inlining: the body is copied into each call site where the concrete type is known. A non-inline function has a single compiled body with an erased `T`, so there is nowhere to substitute the real type.
  • Can a class have a reified type parameter?
    No. `reified` is only allowed on the type parameters of `inline` functions. A class has a single runtime representation, so its type arguments stay erased.

It's like a mail-merge template: the compiler stamps the concrete type into each copy of the function, so the real type is right there instead of a blank T.

saying these in an interview costs you the question

  • Claiming reified works on any generic function without inline
  • Saying Kotlin generics are not erased on the JVM
  • Confusing reified with reflection (it does not read runtime metadata, it substitutes the type at compile time)
  • Thinking you can call a reified function via reflection
  • Believing reified gives full generic info by default (only typeOf<T>() does)

context