Background:
With the rise of functional programming and lambda expressions in the JVM, issues arose regarding the overhead from anonymous objects and additional method calls. In Java, this occurs when using functional interfaces. Kotlin introduced the inline keyword to avoid unnecessary allocations when passing lambda functions.
Problem:
Calling a function with lambda parameters creates anonymous objects on the heap and increases stack depth, which slows down code execution, especially when heavily used in loops and nested calls.
Solution:
Kotlin allows you to declare a function with the inline modifier, after which the function body and the provided lambdas are substituted directly at the call site during compilation. This enables the compiler to eliminate additional allocations and improve performance, especially for short, frequently called functions (like filtering collections).
Code example:
inline fun <T> Iterable<T>.myFilter(predicate: (T) -> Boolean): List<T> { val result = mutableListOf<T>() for (item in this) if (predicate(item)) result.add(item) return result } val filtered = listOf(1, 2, 3, 4).myFilter { it % 2 == 0 } println(filtered) // [2, 4]
Key features:
noinline and crossinline parameters to control inlining of individual lambdas.Can inline functions be used with any functional parameter or generic type T?
No, inline functions primarily save on call overhead for lambda parameters, but the generic parameter itself (like T) is not inlined — a reified modifier is needed for that. For simple T without reified, type information will be erased at compile time.
What happens if an inline function declares a closure over a variable from an external scope?
Variables from the external scope are copied inside the inlined expression. All accesses to them will work as if the code were actually substituted. This can lead to unexpected behavior if you do not anticipate side effects.
Can inline functions be called from Java code?
Yes, but it will be compiled as a regular function, and the Java code will not see any benefits of inlining. Kotlin achieves optimization only when using inline functions from Kotlin code.
return in inline lambdas — improper flow controlA developer inlines a long function with several filtering and post-processing lambdas, expecting a speed-up. The code compiles slowly, the final APK/RAR/DEX significantly increases in size, yet there is no speed gain.
Pros:
Cons:
A small inline function is implemented for short array filters, called hundreds of times in a hot loop — execution time is critically important. Memory allocations are minimal, as the lambda does not create an anonymous object.
Pros:
Cons: