Skip to content
inline + reified Generics
step 1/5

Reading — step 1 of 5

Learn

~1 min readInline + DSL Building

inline tells the compiler to copy the function body to call sites — eliminating the function call overhead AND enabling the reified keyword for generics.

Standard inline:

inline fun measure(block: () -> Unit) {
    val start = System.currentTimeMillis()
    block()
    println("took ${System.currentTimeMillis() - start}ms")
}

measure {
    Thread.sleep(100)
}

No lambda allocation, no virtual call — the body is pasted in at the call site. Big perf win for the standard library's forEach, map, etc.

reified type parameters — only work in inline functions:

inline fun <reified T> List<Any>.filterIsInstance(): List<T> {
    return this.filter { it is T }.map { it as T }
}

val mixed = listOf(1, "hello", 2, "world", 3)
val ints = mixed.filterIsInstance<Int>()       // [1, 2, 3]

Without reified, you can't use T is X or T::class because Kotlin generics are erased at runtime. With inline + reified, the compiler substitutes T at the call site — so the type IS available.

This is how kotlinx.serialization worksJson.decodeFromString<User>(jsonStr) resolves User's class at compile time.

crossinline and noinline — modifiers for lambda parameters of inline functions:

  • noinline — this lambda WON'T be inlined (lets you pass it elsewhere)
  • crossinline — this lambda CAN'T have a non-local return

When to use inline:

  • Higher-order functions called millions of times
  • Functions with reified need
  • DSL builders

When NOT to inline:

  • Large functions (causes binary bloat)
  • Functions that don't take lambdas
  • IDE will warn you when inline isn't beneficial

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…