ProgrammingBackend Developer

What are inline reified parameters (reified generics) in Kotlin, when and why to use them, what are the limitations, and what are some examples of their application?

Pass interviews with Hintsage AI assistant

Answer.

Background:

In the JVM, there is no information about the generics parameters at runtime (type erasure). Kotlin introduced the mechanism of reified generic parameters for inline functions to allow access to information about type T during execution without workarounds like passing Class<T>. This is one of the most powerful features of the Kotlin language.

Problem:

It is required to write a function that accepts some value of type T (generic) and performs different actions depending on the parameter type, without explicitly passing java.lang.Class and without reflection on Java level. Classical type erasure does not allow knowing type T at runtime.

Solution:

In Kotlin, for inline functions, it is allowed to declare generic parameters with the reified modifier, which allows to "capture" type T within the function body, work with it like a regular type, do type-checks, and create instances through reflection.

Code example:

inline fun <reified T> isOfType(value: Any): Boolean { return value is T } isOfType<String>(123) // false isOfType<Int>(123) // true

Key features:

  • Access to type T within the function at runtime
  • Ability to perform type operations like value is T, T::class, T::class.java
  • Works only for inline functions

Trick questions.

Can reified be used outside of inline functions?

No! Only inline functions (and inline lazy properties) can have a reified generic parameter. The reason is the substitution of code at the call site; only this way can you "substitute" a specific type instead of T.

Code example:

// Compilation error: fun <reified T> errorFun() { } // Correct version: inline fun <reified T> okFun() { }

Can you get Class<T> inside an inline reified function?

Yes! You can simply write T::class.java or T::class. This is very convenient for writing generic factories, parsers, and working with the reflection API.

Code example:

inline fun <reified T> printType() { println(T::class.java) } printType<String>() // class java.lang.String

Can instances of type T be created via constructor in a reified function?

Partially. You can use reflection, but directly new T() like in C++ or C# won't work:

inline fun <reified T : Any> makeInstance(): T? { return T::class.constructors.firstOrNull()?.call() }

But this approach requires T to have a no-argument constructor.

Typical errors and anti-patterns

  • Overusing reified too often instead of explicitly passing the type (e.g., everywhere you just need Class<T>)
  • Using reified not for inline functions
  • Expecting to always instantiate T without providing an appropriate constructor

Real-life example

Negative case

Function with reified calling a heavy reflection operation in the code:

inline fun <reified T> foo(): T? = T::class.constructors.firstOrNull()?.call()

Pros:

  • Universal, convenient for tests

Cons:

  • Slow
  • No control over constructor errors, hard to debug

Positive case

Using reified for universal type-check or safeCast:

inline fun <reified T> safeCast(value: Any?): T? = value as? T

Pros:

  • Concise
  • Safe (as?)
  • No performance overhead

Cons:

  • Supported only in inline functions