目录
1、inline 背景
inline---内联函数
当我们在使用高阶函数的时候,因为除了高阶函数本身是个函数以外,它的参数或者返回值也是一个Lambda函数,lambda函数内部还有局部变量,当在编译运行的时候,因为每一个Lambda函数都是一个对象,并且还会捕获一个闭包及闭包内会访问到的变量。 这样在内存分配(对于函数对象和类)和虚拟机调用上都会加大运行时间开销。
为了解决高阶函数所带来的额外开销,kotlin加入了inline关键字。
注意:过多的使用inline关键字会对编译器造成很大的性能压力,所以我们建议只在高阶函数中使用inline关键字。
2、inline 原理
代码在编译以后,会将内联函数的函数体复制到调用处。
下面左边是我们的inline函数,右边是我们编译后的class文件。
从编译后的class可以看出,inline的函数体会被直接复制到调用该内联函数的地方。
3、noinline
因为inline是用来修饰高阶函数的,又因为被inline修饰的高阶函数,其参数中的lambda函数也会隐式变成inline函数,但如果我们不想要将lambda参数内联化的话,就可以使用noline关键字。
下面左边是kotlin代码,右边是编译后的class文件,绿色框中,就是我们内联化的 lambda函数a,红色就是没有被内联化的lambda函数b。
4、crossinline
crossinline的作用就是:不允许inline的lambda函数中断外部函数执行。
- 在kotlin中,函数内部lambda是不允许中断外部函数执行的。(如果有return检查期会报错)
fun test1(a:()->Unit){
a.invoke()
return
println("我在return后面")
}
fun main() {
test1 { println("我是Lambda函数a")
//return--------------------------------报错,无法return
}
println("我在test1后面")
}
//输出结果
我是Lambda函数a
我在test1后面
- inline修饰的lambda可以中断外部函数调用(原理:会将return复制到main函数中,所以return后面的语句就无法执行了)
inline fun test1(a: () -> Unit) {
a.invoke()
return
println("我在return后面")
}
fun main() {
test1 {
println("我是Lambda函数a")
return
}
println("我在test1后面")
}
//输出结果
我是Lambda函数a
- 在inline的修饰的高阶函数中,将参数中的lambda函数用crossinline修饰就不会中断外部函数的执行。
inline fun test1(crossinline a: () -> Unit) {
a.invoke()
return
println("我在return后面")
}
fun main() {
test1 {
println("我是Lambda函数a")
// return-----------------------报错,无法使用return
}
println("我在test1后面")
}
//输出结果
我是Lambda函数a
我在test1后面
5、注意
break
和continue
在内联的 lambda 表达式中目前还不可用。