noinline 与 crossinline 修饰符
控制 inline 函数中特定 Lambda 参数的内联行为。
noinline 与 crossinline 修饰符 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
inline 要解决并引入的问题
函数为 inline 时,其所有匿名函数参数默认都会被内联。有时您需要指定某个匿名函数不被内联,例如需要将它存储起来,或将它传递给另一个非内联函数。
noinline:将一个匿名函数保留为对象
在指定的匿名函数参数前加上 noinline,即可选择不对其进行内联,同时保留其余参数的内联行为。
inline fun doWork(
action: () -> Unit,
noinline callback: () -> Unit // stored, not inlined
) {
action() // inlined at call site
scheduleCallback(callback) // passed as object — valid
}必须使用 noinline 的情况
在以下情况下必须使用 noinline:
- 匿名函数存储在变量或字段中
- 匿名函数被传递给需要函数类型的另一个函数
- 匿名函数从内联函数中返回
crossinline:禁止非局部返回
当内联匿名函数将在不同的执行上下文中调用(例如在另一个匿名函数内部或另一个线程中)时,可以使用 crossinline。它会告诉编译器:内联这个匿名函数,但不允许其中出现非局部返回。
inline fun runAsync(crossinline block: () -> Unit) {
Thread {
block() // block is inlined but cannot use non-local return
}.start()
}非局部返回为何在此处有风险
如果 block 可以使用非局部 return,它就会尝试从调用 runAsync 的函数中返回。但在线程运行时,该函数可能已经返回,从而导致未定义行为。crossinline 会在编译时阻止这种情况。
组合使用 noinline 和 crossinline
一个内联函数可以混合使用普通参数、noinline 参数和 crossinline 参数:
inline fun orchestrate(
crossinline setup: () -> Unit,
action: () -> Unit,
noinline teardown: () -> Unit
) {
Thread { setup() }.start()
action()
register(teardown)
}没有 crossinline 时的编译器错误
如果将内联匿名函数传递到匿名函数上下文中,却没有使用 crossinline,编译器会发出以下错误:“无法在此处内联代码块:它可能包含非局部返回。请添加 crossinline 修饰符。”
标准库中的使用
标准库在 Sequence { } 等函数以及某些协程构建器中使用 crossinline,确保用户提供的匿名函数能够在不同上下文中安全运行。
noinline 不会破坏 inline
将一个参数标记为 noinline 不会关闭整个函数的内联。函数体和其他所有匿名函数参数仍会被内联。只有标记为 noinline 的匿名函数会保留其对象身份。
性能注意事项
noinline 会让该参数承担通常的匿名函数分配开销。crossinline 仍然会进行内联,唯一的限制是不允许非局部返回。这两个修饰符都不会影响其他参数的内联。
总结表
修饰符总结:
- 没有修饰符 → 匿名函数完全内联,允许非局部返回
noinline→ 匿名函数保留为对象,可以存储或传递crossinline→ 匿名函数会被内联,但禁止非局部返回
快速检查
什么时候必须在 inline 函数的匿名函数参数上使用 noinline?
回顾:noinline 与 crossinline
关键要点:
noinline:在一个原本内联的函数中,将一个匿名函数保留为对象crossinline:内联匿名函数,但禁止非局部返回,以便安全地跨上下文使用- 这两个修饰符都分别应用于参数,而不是整个函数
常见问题解答
「noinline 与 crossinline 修饰符」课时是免费的吗?
是的 — 「noinline 与 crossinline 修饰符」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「noinline 与 crossinline 修饰符」这节课中我会学到什么?
控制 inline 函数中特定 Lambda 参数的内联行为。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「noinline 与 crossinline 修饰符」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- inline 函数:消除 Lambda 开销
- noinline 与 crossinline 修饰符
- reified 类型参数:在运行时访问 T
- 实用的 Reified 模式:解析、DI 与序列化