🌟 什么是内联函数?

简单说:

内联函数就是在编译时将函数的调用代码“展开”为函数体本身,从而避免函数调用的开销。

通常高阶函数(比如 map, filter, let, run 等)都会带来额外的开销,因为它们需要创建函数对象、维护调用栈。而使用 inline 关键字修饰的函数在编译时会将其代码“拷贝”到调用处,避免这些额外开销。


🧪 基本语法

1
2
3
4
5
inline fun doSomething(action: () -> Unit) {
println("Start")
action()
println("End")
}

调用方式:

1
2
3
doSomething {
println("Hello inline")
}

⚡ 编译后,大致等价于:

1
2
3
println("Start")
println("Hello inline")
println("End")

函数体直接“插入”到调用处。


✅ 优势

  1. 性能提升:避免函数调用、lambda 对象创建的开销。
  2. 允许非局部返回(下面详细说)
  3. 适合频繁调用的小型函数或高阶函数

⚠️ 注意:非局部返回(non-local return)

Lambda 中用 return,默认是从外围函数返回的,这在内联函数中是允许的。

1
2
3
4
5
6
7
8
9
10
11
12
13
inline fun doSomething(block: () -> Unit) {
println("Before")
block()
println("After") // 不会执行
}

fun test() {
doSomething {
println("Inside")
return // 非局部 return,直接从 test() 返回
}
println("This will not be printed")
}

如果你把 doSomethinginline 去掉,这段代码是无法通过编译的。


🔒 使用 noinline 禁止内联某个 lambda

有时候你不希望某些 lambda 被内联,可以加 noinline

1
2
3
4
inline fun process(a: () -> Unit, noinline b: () -> Unit) {
a() // 内联
b() // 不内联
}

常用于 将 lambda 作为值传递或多次使用 的情况。


💥 crossinline:阻止 lambda 使用 return

有时候你必须内联,但又不允许 lambda 使用非局部 return(比如 lambda 传给另一个线程或匿名类),你可以加 crossinline

1
2
3
4
5
inline fun startJob(crossinline job: () -> Unit) {
Thread {
job() // 如果 job 用 return 会报错
}.start()
}

🚀 小总结

关键字 作用
inline 编译时将函数体展开,提升性能,允许非局部 return
noinline 禁止某个 lambda 被内联(用于多次调用或当作对象传递)
crossinline 阻止某个 lambda 使用 return(防止非局部 return)

✅ 典型应用场景

  • apply / run / let 等标准库函数内部都是 inline
  • DSL 构建器,比如 anko, Jetpack Compose, Ktor 等大量用 inline 优化性能和语法结构
  • 性能敏感的高阶函数