inline
- 用在函数上,告诉编译器在调用处展开函数体,而不是生成函数调用。常用于高阶函数(函数参数),可以减少 lambda 对象的创建 和 虚拟调用开销。
- 在高阶函数中使用 inline,支持 lambda(不加 crossinline/noinline)非局部返回(non-local return)。
inline fun doSomething(action: () -> Unit) {
println("Before action")
action() // lambda 会直接展开到这里
println("After action")
}
fun main() {
doSomething {
println("Hello")
return // 非局部返回:直接从 main 返回
}
println("This line is unreachable") // 因为 lambda 非局部返回
}
inline 是针对函数本身和它的 lambda 参数一起展开的,而不仅仅是 lambda 参数。当然主要的收益还是 lambda 参数也会被展开,所以当 inline 修饰的函数本身不带有 lambda 参数时,IDE 会告警:
Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of function types.
crossinline
用在 inline 函数的 lambda 参数上,禁止非局部返回(non-local return),lambda 允许被内联。
为什么需要 crossinline? 如果 lambda 被内联,但不能保证 lambda 调用的上下文允许非局部返回,就需要加 crossinline 禁止 lambda 内部直接从调用函数返回。
inline fun doSomethingCross(crossinline action: () -> Unit) {
val runnable = Runnable {
action() // lambda 会展开到这里,但是不能使用非局部 return
}
runnable.run()
}
fun main() {
doSomethingCross {
println("Hello")
// return // ❌ 编译错误,crossinline 禁止非局部返回
}
}
noinline
用在 inline 函数的 lambda 参数上,告诉编译器不要内联这个 lambda,同时禁止非局部返回(non-local return)。适合:
- lambda 参数需要 保存为变量 或 传递给其他函数
- 避免 lambda 被内联导致不必要的非局部返回限制
inline fun doSomethingInline(noinline action: () -> Unit) {
println("Before action")
action() // lambda 不会展开到这里,也不能使用非局部 return
println("After action")
}
fun main() {
// 可以安全保存
val savedAction = {
println("Saved action")
// return // ❌ 编译错误,noinline 禁止非局部返回
}
doSomethingInline(savedAction)
}