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 标记跨内联,保持内联优化,可以间接调用,不允许非局部返回
相关推荐
Kapaseker15 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z3 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton3 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream3 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam3 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker4 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc4 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景5 天前
kotlin协程学习小计
android·kotlin
Kapaseker5 天前
你搞得懂这 15 个 Android 架构问题吗
android·kotlin
zh_xuan5 天前
kotlin 高阶函数用法
开发语言·kotlin