Inline Functions & reified
An inline function is copied directly into each call site by the compiler, eliminating the object allocation a passed lambda would otherwise need and enabling reified type parameters that survive at runtime.
Learn Inline Functions & reified in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll learn why higher-order functions benefit from inline , how reified lets you check a generic type at runtime, and what noinline and crossinline are for.
What You'll Learn in This Lesson
1️⃣ What inline Does (and Why It Helps)
Marking a function inline asks the compiler to paste its body — and the body of any lambda you pass to it — directly where the function is called, instead of generating a real call. The program behaves identically; only the compiled bytecode changes. The payoff appears with higher-order functions: a passed lambda would normally become a heap-allocated object, and inlining removes that object entirely.
For a one-off call the difference is invisible, but inside a loop that runs millions of times, removing the per-call lambda allocation is exactly why Kotlin's map , filter , and forEach are all declared inline .
2️⃣ reified: Knowing T at Runtime
On the JVM, generic types are normally erased — at runtime a generic function has no idea what T was, so item is T won't compile. Because an inline function is copied into each call site, the compiler can substitute the real type there. Marking the type parameter reified unlocks exactly that, letting you write is T and T::class .
reified is only allowed on inline functions, because the type substitution happens precisely during the copy-into-call-site step.
3️⃣ A Real reified Helper (and noinline / crossinline)
The standard library's filterIsInstance<T>() is built from these ideas. Here we write our own. Two modifiers refine inlining: noinline on a lambda parameter keeps that one lambda as a real object (so you can store or forward it), and crossinline forbids non-local returns when a lambda is invoked from another context.
You rarely need noinline or crossinline day to day — plain inline plus reified covers the vast majority of real code.
Your turn. Fill in the ___ , then run and compare.
Mini-Challenge: Count by Type
Write a reified function that counts how many list items match a given type.
Common Errors (and the fix)
- ❌ "Cannot check for instance of erased type: T" — You wrote is T on a plain generic. ✅ Make the function inline and the parameter reified .
- ❌ "Reified type parameter is only allowed for inline functions" — You used reified without inline . ✅ Add the inline modifier.
- ❌ "Illegal usage of inline-parameter" — You tried to store or return an inlined lambda. ✅ Mark that parameter noinline .
- ❌ Inlining a huge function — Marking a large body inline bloats bytecode for no benefit. ✅ Only inline small functions that take lambdas or need reified .
Pro Tips
- 💡 Use the built-in: list.filterIsInstance<String>() already does the reified filtering for you.
- 💡 reified shines in factories: APIs like JSON parsers use inline fun <reified T> parse(...) so callers write parse<User>(json) with no extra class argument.
- 💡 Measure before optimizing: reach for inline for reified or genuine hot paths, not by default.
📋 Quick Reference — inline & reified
Concept
Kotlin Syntax
Inline function
inline fun run(block: () -> Unit)
Reified type
inline fun <reified T> f()
Runtime type check
if (item is T) ...
Get the class
T::class.simpleName
Keep lambda as object
noinline block: () -> Unit
Forbid non-local return
crossinline block: () -> Unit
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ inline copies a function's body into the call site
- ✅ Inlining removes the heap allocation of a passed lambda
- ✅ Higher-order functions benefit most, especially in loops
- ✅ reified keeps a generic type available at runtime
- ✅ noinline and crossinline refine lambda behaviour
- ✅ Next lesson: Sequences (Lazy Collections)
Practice quiz
What does marking a function 'inline' do?
- Runs it on a separate thread
- Copies its body into each call site
- Makes it asynchronous
- Caches its return value
Answer: Copies its body into each call site. inline copies the function body — and passed lambdas — directly into the call site.
Which functions benefit most from inlining?
- Functions with no parameters
- Recursive functions
- Higher-order functions that take lambdas
- Functions returning Unit
Answer: Higher-order functions that take lambdas. Inlining removes the per-call lambda object, so higher-order functions benefit most.
What problem does inlining a lambda parameter avoid?
- Heap allocation of a lambda object
- Stack overflow
- Type erasure of return types
- Null pointer exceptions
Answer: Heap allocation of a lambda object. Normally each passed lambda becomes a heap object; inlining removes that allocation.
A 'reified' type parameter is only allowed on which kind of function?
- Suspend functions
- Abstract functions
- Extension functions
- inline functions
Answer: inline functions. reified requires inline, because the type is substituted as the body is inlined.
What does reified let you write that a plain generic cannot?
- item is T and T::class
- a return statement
- a default argument
- a nullable type
Answer: item is T and T::class. With reified, T survives at runtime so you can write is T and T::class.
Why is 'item is T' normally illegal in a generic function?
- T must be a class
- Generic types are erased at runtime on the JVM
- is only works on numbers
- T is always null
Answer: Generic types are erased at runtime on the JVM. JVM type erasure removes T at runtime, so is T won't compile without reified.
What does 'noinline' on a lambda parameter do?
- Forbids returning from the lambda
- Makes the whole function inline
- Keeps that one lambda as a real object so it can be stored or passed on
- Deletes the lambda
Answer: Keeps that one lambda as a real object so it can be stored or passed on. noinline keeps that lambda as a real object so you can store or forward it.
What does 'crossinline' enforce?
- It forbids non-local returns from the lambda
- It forces inlining of all callers
- It makes the lambda nullable
- It reifies the type parameter
Answer: It forbids non-local returns from the lambda. crossinline forbids non-local returns when the lambda is invoked from another context.
Which standard library function is built on reified type filtering?
- mapNotNull
- filterIsInstance
- groupBy
- associateWith
Answer: filterIsInstance. filterIsInstance<T>() uses an inline reified type parameter to filter by type.
What is a downside of marking a large function inline?
- It becomes thread-unsafe
- It can bloat the generated bytecode
- It cannot return a value
- It loses type safety
Answer: It can bloat the generated bytecode. Inlining copies code, so inlining big bodies bloats bytecode for little benefit.
Continue this course
- Previous: Higher-Order Functions
- Next: Sequences