Kotlin inline、noinline 和 crossinline 的区别

Kotlin inline、noinline 和 crossinline 的区别

  • 间接调用:比如作为参数传递给其他函数或作为返回值返回
  • 非局部返回:Lambda 中 return 直接返回外层函数的情况,而局部返回就是 return 返回到这个函数本身

inline 内联函数

  • 用于标记一个函数为内联函数,在编译时将函数体代码(包括参数)直接内联展开嵌入到调用处(函数中的代码直接复制到调用它的地方),而不是通过传统函数调用(压栈进栈)的方式执行,从而减少函数调用和对象创建等额外的开销,inline 适合用在包含 Lambda 参数的函数上
  • 函数调用:减少函数调用栈的开销(减少函数栈的层级),调用一个方法是一个压栈和出栈的过程
  • 对象创建:调用高阶函数(带 Lambda 参数)而创建函数对象(比如 Function 接口的实例)
  • inline 不仅让函数调用被内联,还会让函数参数也被内联,它可以让函数参数里面的直接 return 生效(因为普通 Lambda 不能直接使用 return),在 inline 函数的 Lambda 中可以使用 return 直接返回到调用该函数的外层函数(而非 Lambda 自身),相当于会退出外层函数,不过这其实算是一个缺点,因为代码逻辑很容易出现不是想象中预期的结果,所以引入了一种方式解决,就是利用 noinline 或 crossinline 来限制在 Lambda 中直接使用 return 的行为
kotlin 复制代码
inline fun fun01(block: () -> Unit) {
    block() //调用 Lambda
}
fun main() {
    fun01 {
      println("Test01") 
      return //直接退出 main 函数(支持 return 返回到外层函数),如果没有 inline 标记的话,编译器会报错(不过可以改成 return@fun01,但是这样只会退出 Lambda)
    }
    println("Test02") //这行代码不会执行
}

noinline 禁止内联特定参数

  • 与 inline 结合使用,用于标记一个函数的某个参数(通常是 Lambda)不被内联,Lambda 会像普通函数参数一样(作为普通的函数对象传递),相当于使用 noinline 来指定某个函数参数不使用 inline 带来的特性
  • 间接调用:如果需要将 Lambda 传递给其他非内联函数时(因为内联函数的函数参数是不允许作为参数传递给非内联的函数的),就必须使用 noinline,如果需要将 Lambda 作为返回值返回时,必须使用 noinline
kotlin 复制代码
inline fun fun02(
    action: () -> Unit,              //内联
    noinline callback: () -> Unit    //不内联
) {
    action()
    callback()
}
fun main() {
    fun02({
        println("Test01")
        //return  //这里直接用 return 编译器不会报错
    }, {
        println("Test02")
        //return  //这里直接用 return 编译器会报错
    })
    println("Test03")
}

crossinline 跨内联限制非局部返回

  • 用于标记一个函数的某个 Lambda 参数,表示该 Lambda 可以被间接调用,但禁止在 Lambda 中使用 return(可以确保 Lambda 中不会出现非局部返回,防止 return 意外跳出外层函数),避免因内联导致 return 作用域混乱
  • 保持内联优化:crossinline 标记的 Lambda 仍会被内联展开(除非被传递到非内联函数中)
kotlin 复制代码
inline fun fun03(crossinline block: () -> Unit) {
    block() //调用 block 时,不能通过 return 返回到外层函数
}
fun main() {
    fun03 {
        return //这里直接用 return 编译器会报错(crossinline 禁止使用 return)
    }
}

总结

  • 普通函数(带 Lambda 参数),可以间接调用,不允许非局部返回
  • inline 标记整个函数为内联函数,不可以间接调用,允许非局部返回
  • noinline 标记禁止某一个参数内联,可以间接调用,不允许非局部返回
  • crossinline 标记跨内联,保持内联优化,可以间接调用,不允许非局部返回
相关推荐
tangweiguo0305198740 分钟前
Android并发编程:线程池与协程的核心区别与最佳实践指南
android·kotlin
三少爷的鞋6 小时前
动态属性计算:Kotlin 中的自定义 Getter
kotlin
程序员江同学20 小时前
Kotlin 技术月报 | 2025 年 3 月
android·kotlin
前行的小黑炭21 小时前
Android:如何看Github、Gitee上的项目提升自己的能力?一条龙服务,尤其是有了DeepSeek以后。
android·kotlin·deepseek
前行的小黑炭1 天前
Kotlin的委托是什么?在看源码的时候不知道他的作用是什么,为什么使用,那么你看看这篇文章。
android·kotlin
前行的小黑炭1 天前
Kotlin的扩展函数:给任何类添加你想要的功能,即使是自带类,第三方类。
android·kotlin
Yang-Never1 天前
Open GL ES ->模型矩阵、视图矩阵、投影矩阵等变换矩阵数学推导以及方法接口说明
android·矩阵·kotlin·android studio
彼方卷不动了2 天前
【技术学习】在 Android 上用 Kotlin 实现支持多图层的 OpenGL 渲染管线
android·kotlin·opengl
行墨2 天前
Kotlin高阶函数初探
kotlin
wangz762 天前
kotlin,jetpack compose 最简导航(navigation)案例学习
kotlin·navigation·jetpack compose