一次性搞懂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,到这里,关于内联函数相关的东西就差不多了,欢迎留言跟我讨论哈~