Kotlin 内联函数

Kotlin 的 内联函数(inline function) 是一种优化手段 ,它允许在编译时将函数的代码"展开"到调用处,从而避免函数调用的开销,尤其适用于 高阶函数(接受函数作为参数) 的场景。

什么是内联函数

正常函数调用会产生函数对象、栈帧和跳转指令,但内联函数会在编译时将函数代码插入到调用点,避免这些开销。

kotlin 复制代码
inline fun doSomething(block: () -> Unit) {
    println("Before")
    block()
    println("After")
}

fun main() {
    doSomething {
        println("Hello")
    }
}

编译后大致等价于:

kotlin 复制代码
fun main() {
    println("Before")
    println("Hello")
    println("After")
}

函数体会"复制粘贴"到调用点。

什么时候使用 inline

Kotlin 中高阶函数 (比如 letrunwithapply)频繁使用内联,避免函数对象的创建(block: () -> Unit 不会生成 Function 对象),避免 lambda 的闭包捕获、堆分配和 GC 开销。普通业务函数不推荐使用内联,会导致代码膨胀。

inline 的工作原理

内联函数不是运行时特性,而是编译器替换机制inline fun foo(block: () -> Unit) 编译器看到后就会展开 block() 的实现到调用点。如果有多个调用点,会展开多次(可能造成代码膨胀)。

使用 return@label可以局部返回:

kotlin 复制代码
inline fun doSomething(block: () -> Unit) {
    block()
}

fun main() {
    doSomething {
        println("Inside block")
        return@doSomething // 局部返回,不影响 main
    }
    println("After")
}

如果不加 inline 会怎么样,编译器会生成 Function 实例(Function0),lambda 体被封装为对象,可能造成性能下降,尤其是在 Android 中。

kotlin 复制代码
fun doSomething(block: () -> Unit) {
    block()
}

noinline 与 crossinline

noinline

默认情况下,所有函数参数都会被内联。但你可以用 noinline 排除部分参数:

kotlin 复制代码
inline fun test(block1: () -> Unit, noinline block2: () -> Unit) {
    block1()  // 被内联
    block2()  // 作为函数对象
}

noinline 主要用于函数参数需要作为对象传递,以及不能内联的上下文(如存储到变量)。

kotlin 复制代码
inline fun doOps(
    inlineBlock: () -> Unit,
    noinline logging: () -> Unit  // 这里阻止了 logging 被内联
) {
    inlineBlock()   // 内联
    val func = logging  // 如果不加 noinline 会编译错误,因为不能传递被内联的 lambda
    func()
}

crossinline

禁止 lambda 用 return 做"非局部返回"。默认情况下,内联 lambda 可以直接 return,但有风险。

kotlin 复制代码
inline fun higherOrder(block: () -> Unit) {
    println("Before")
    block()
    println("After") // 如果 block 里直接 return,这行永远不会执行
}

fun test() {
    higherOrder {
        return  // 这是"非局部返回":会从 test() 函数直接返回
    }
}

要禁止这种"跳出上层函数"的行为,加 crossinline

kotlin 复制代码
inline fun higherOrder(crossinline block: () -> Unit) {
    println("Before")
    block()
    println("After") // 如果 block 里直接 return,这行永远不会执行
}

fun test() {
    higherOrder {
        return  // 现在 block() 里面不能写 return 了,这里会报错,但是依然可以写 return@higherOrder
    }
}

注意事项与风险

代码膨胀

kotlin 复制代码
inline fun heavy(block: () -> Unit) { ... }

repeat(1000) {
    heavy { ... } // 编译后生成 1000 份代码
}

函数体复杂,调用频繁时,会导致APK 变大,方法数上升。

调试困难

内联函数展开后,调试栈信息会变得混乱,调试时跳转不准。

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax