Kotlin Inline, NoInline, and CrossInline Features
Overview
enline: During compilation, the function's code is copied to the call site.
noinline: Used for lambda parameters in inline higher-order functions that should not be inlined. crossinline: Ensures that a lambda parameter in an inline higher-order function cannot contain non-local returns and must be called indirectly.
Usage Analysis
1. Local Returns: Only return from the current block.
Lambda expressions default to returning the last line, and they cannot use non-local returns (i.e., return statements without labels).
fun main() {
higherFun(lambdaOne@ {
println("called lambdaOne")
return@lambdaOne
})
}
fun higherFun(block: () -> Unit) {
block()
}
2. Inline Inlining
Functions marked with inline can inline their own code as well as the code inside their lambda expressions.
public fun initView(savedInstanceState: Bundle?) {
......// omitted code
higherFun2 {
Log.d("Cding", "=====================higherFun2 lambda 1")
// Within the lambda of an inline higher-order function, you can directly return, which returns to the outer function calling this higher-order function.
// The code after this return will not execute, nor will the code following the higher-order function call in the outer function.
return
Log.d("Cding", "=====================higherFun2 lambda. 2")
return@higherFun2 "higherFun2"
Log.d("Cding", "=====================higherFun2 lambda. 3")
"String of return."
}
}
private inline fun higherFun2(block: (Int) -> String) {
block.invoke(200)
Log.d("Cding", "=====================higherFun2 before return.")
return
Log.d("Cding", "=====================higherFun2 after return.")
}
The compiled code to higherFun2 is directly moved to the call site:
public fun initView(@Nullable savedInstanceState: Bundle?) {
this.extFun();
Function1 lambda1 = (Function1)null.INSTANCE;
Function1 lambda2 = (Function1)null.INSTANCE;
this.higherFun((Function1)null.INSTANCE);
int $i$f$higherFun2 = false;
int it = true;
int var7 = false;
// Code from higherFun2
Log.d("Cding", "=====================higherFun2 lambda 1");
String str = "String of return.";
}
noinline
Parameters of inline higher-order functions can only be passed to other inline higher-order functions, not to regular ones. Use noinline to prevent inlining of the lambda parameter.
inline fun hightFunNoLine(block1: (Int, String) -> String, noinline block2: () -> Unit) {
val start = 0
val end = "end"
block1.invoke(start, end)
commonHigherFun(block2)
}
fun commonHigherFun(block: () -> Unit) {
block.invoke()
}
Without noinline, block2 cannot be passed to commonHigherFun. The noinline keyword disables inlining.
crossinline
crossinline: Enhances inline optimization, allowing a lambda parameter inside an inline higher-order function to be called indirectly, but prevents using return within the lambda.
/**
* When using a lambda inside an inline higher-order function, it can perform non-local returns.
* However, when using a lambda inside an inline function's anonymous class, non-local returns are disallowed.
*/
private inline fun higherFun3(crossinline block: (Int, String) -> String) {
val start = 0
val end = "end"
val function = object : MFunction {
override fun invoke() {
block(start, end)
}
}
}
private interface MFunction {
fun invoke()
}