Inline functions in Kotlin
Higher-order functions are convenient, but they carry a cost — in general each passed lambda becomes an object allocated on the heap, and its call goes through a virtual invoke(). inline removes that cost: the compiler copies the function body and its lambda arguments straight into the call site, so no lambda object is created at all. This is a key standard-library optimization — forEach, let, apply are all inline.
Inlining has a non-obvious consequence that interviews love. Since the lambda body is copied into the calling function, a bare return inside such a lambda exits the enclosing function — that is a non-local return. Two modifiers control this: crossinline forbids a non-local return, noinline disables inlining of a parameter entirely. The full map lives in the layers below.
Topic map
- Inline functions — what
inlinedoes, why, and whynoinlineexcludes a parameter from inlining. - Non-local return — why a bare
returnfrom an inlined lambda exits the enclosing function, and how to return from the lambda only. - Crossinline — when an inlined lambda may not enter another context, and how
crossinlinefixes it.
Common traps
| Mistake | Consequence |
|---|---|
Treating inline as merely a speed hint | You miss its effect on return semantics and on reified |
| Inlining a large function | The body is copied into every call site — code bloat |
Thinking a bare return in a lambda exits only the lambda | In fact a non-local return exits the enclosing function |
Reading crossinline as a harmless optimization | It is a ban on non-local return — add it needlessly and you break a working return |
Fixing with noinline when crossinline is needed | noinline also disables inlining of the lambda |
Marking a parameter reified without inline | Does not compile — reified is only possible under inlining |
Interview relevance
The topic is asked to check whether you understand the inlining mechanics, not just the word "faster". A candidate who explains "inline copies the body into the call site, so a return from a lambda exits the enclosing function, and crossinline forbids that exit" gets ahead of "inline is an optimization".
Typical checks:
- What
inlinedoes and at what cost (code size versus lambda allocation). - What a non-local return is and how to return from the lambda only (
return@label). - The difference between
crossinlineandnoinlineand when each is needed. - The link between
inlineand reified type parameters.
Common wrong answer: "inline caches the result" or "crossinline is about performance". In fact inline is about inlining the body, and crossinline is about forbidding a non-local return so the lambda can be safely called from another execution context.