Kotlin Inline, Noinline, Crossinline, Reified

Manuchekhr Tursunov
3 min readApr 13, 2023

--

Inline

In Kotlin, inline functions are used to improve performance by avoiding the overhead of creating objects for lambdas or function objects. The inline keyword is used to mark a function as inline, and the function is then copied into the call site instead of being executed as a separate function call.

Here’s an example of an inline function:

inline fun measureTimeMillis(block: () -> Unit): Long {
val startTime = System.currentTimeMillis()
block()
return System.currentTimeMillis() - startTime
}

In this example, the measureTimeMillis function takes a lambda expression as a parameter and measures the time it takes to execute the block of code inside the lambda.

Inline variables are a new feature introduced in Kotlin 1.5. They allow for the definition of a property whose getter/setter functions are inlined. Inlining a property means that the property access is replaced by the code inside the getter/setter functions at compile time, rather than at runtime. This can lead to improved performance in certain cases.

Here’s an example of using an inline variable:

inline var Int.incremented: Int
get() = this + 1
set(value) { throw UnsupportedOperationException("Cannot set value") }

In this example, we’ve defined an inline extension property on the Int class called incremented. This property has a getter function that returns the value of the integer plus one, and a setter function that always throws an exception if someone tries to set the value.

To use this property, we can simply call it on an integer value, like this:

val x = 5
val y = x.incremented

In this case, y would have a value of 6.

New example:

inline var counter = 0

inline fun incrementCounter() {
counter++
}

inline fun printCounter() {
println(counter)
}

fun main() {
incrementCounter()
printCounter() // prints "1"
}

It’s worth noting that inline variables should be used with caution, as they can easily lead to code bloat and larger compiled code size. They should only be used in cases where the performance benefits outweigh the potential drawbacks.

Noinline

The noinline keyword is used to mark a lambda parameter as not being inlined, even if the function itself is marked as inline. This is useful when you want to pass a lambda expression to a higher-order function, but don't want it to be inlined.

Here’s an example of using noinline:

inline fun execute(block: () -> Unit, noinline errorHandler: (Throwable) -> Unit) {
try {
block()
} catch (e: Exception) {
errorHandler(e)
}
}

In this example, the execute function takes a lambda expression and a noinline lambda expression as parameters. The block parameter is inlined, while the errorHandler parameter is not.

Crossinline

The crossinline keyword is used to ensure that a lambda expression is not allowed to have a non-local control flow, such as a return statement. This is useful when you want to pass a lambda expression to a higher-order function, but don't want it to be able to break out of the function.

Here’s an example of using crossinline:

inline fun executeOnMainThread(crossinline block: () -> Unit) {
val handler = Handler(Looper.getMainLooper())
handler.post {
block()
}
}
inline fun foo(crossinline callback: () -> Unit) {
val runnable = Runnable { callback() }
// post to handler
}

In this example, the executeOnMainThread function takes a crossinline lambda expression as a parameter and posts it to the main thread using a Handler.

The reified keyword is used in conjunction with inline functions to allow type parameters to be accessed at runtime. This is useful when you want to check the type of a generic parameter at runtime, which is not normally possible in Kotlin due to type erasure.

Here’s an example of using reified:

inline fun <reified T> isOfType(value: Any): Boolean {
return value is T
}
inline fun <reified T> findFirst(items: List<Any>): T? {
for (item in items) {
if (item is T) {
return item
}
}
return null
}

In this example, the isOfType function takes an Any value and a type parameter T, which is marked with the reified keyword. The function then checks if the value is an instance of the specified type T.

Overall, these features of Kotlin provide developers with powerful tools to write more concise and performant code.

--

--