欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一次性搞懂Kotlin的内联函数--inline,noinline和crossinline

程序员文章站 2022-03-15 19:25:21
...

inline 内联函数
  编译时把函数的实现直接放到调用处,省去了参数对象的创建,减少了调用的层级。一般是用在高阶函数里。
  内联函数的参数,如果是函数类型(即lambda),调用时,可以使用return(特权),那么返回的就是调用函数的那个函数

private inline fun inLinTest(f1: () -> Unit, f2: () -> Unit ){
    Log.i(TAG, "inline test")
    f1() //runOnUiThread { f1() } location 1
    f2()
}
//调用
inLinTest({
    Log.i(TAG, "parm1")
    return
}, {
    Log.i(TAG, "parm2")
})

会被编译成如下代码

Log.i(TAG, "inline test")
Log.i(TAG, "parm1")
return
Log.i(TAG, "parm2")

  可以看到,函数的参数,甚至函数名,都被“优化”掉了,因此代码中的parm2就不会被打印。
  如果内联函数的参数是lambda,那么该参数就不能再作为函数的参数(传参)或者返回值了,因为内联函数在编译的时候,函数以及参数都没有参与到代码里,那么内存里面就没有参数了,又怎么能作为参数或者返回值呢?如果要打破这个限制就需要下面的两个东东了。
noinline
被修饰的部分不使用内联,这样的话,就可以作为函数的参数和返回值了,如下:


private inline fun inLinTest(noinline f1: () -> Unit, f2: () -> Unit ){
    Log.i(TAG, "inline test")
    runOnUiThread { f1() } //f1作为参数传递,没有问题,如果需要亦可作为返回值
    f2()
}
//调用
inLinTest({
    Log.i(TAG, "parm1")
    // return location 1 
}, {
    Log.i(TAG, "parm2")
})

  但是这样的话,调用的时候,location 1处就不能使用return返回了,因为如果返回的话,只是能出runOnUiThread(),而我们上面说的是返回函数外面一层的函数,就不成立了。
crossinline
  一般的inline函数的lamda类型的参数是不能当做参数传递的,但是加上了crossinline就可以了,但是注意不能当做函数的返回值。
  来比对一下noinline 和 crossinline
相同点:调用的时候,lambda里面不能使用return返回,都可以作为函数的参数传递。
不同点:被crossinline修饰的lambda参数,不能当做函数的返回值。
  ok,到这里,关于内联函数相关的东西就差不多了,欢迎留言跟我讨论哈~