原因/定义:
使用高阶函数会带来一些运行时的效率损失:每一个函数都是一个对象,并且会捕获一个闭包;即那些在函数体内会访问到的变量;内存分配(对于函数对象和类)和虚拟调用会引入运行时间开销。但是在许多情况下通过“内联化lambda表达式”可以消除这类的开销。
普通函数怎么定义成内联函数?
实现:
就是在前面加“inline”关键字
inline fun printMsg(){
println("Hello, Kotlin!!!")
}
就这样,“printMsg()”就是一个内联函数了。
作用:
减少函数调用以及因此引起的开销,优化性能;inline 修饰符影响函数本身和传给它的 lambda 表达式:所有这些都将内联到调用处。
在实际使用中,高阶函数更适合定义为内联函数:米茨调用高阶函数,都会传一个lambda表达式,而这个lambda表达式是一个匿名函数的语法糖,谈本市也是一个函数。
下面直接上代码说明:
costs {
println("Hello, Kotlin!!!")
}
inline fun costs(block:() -> Unit){
val start = System.currentTimeMillis();
block()
println("${System.currentTimeMillis() - start}")
}
上面的示例代码,我们可以这样理解:
“costs(block:() -> Unit)”函数里面的参数(本质上是个方法)block就是上面的 costs {println(“Hello, Kotlin!!!”)}里面的“println(“Hello, Kotlin!!!”)”
当系统真正调用执行的时候,本质上相当于这样:
val start = System.currentTimeMillis();
println("Hello, Kotlin!!!")
println("${System.currentTimeMillis() - start}")
高阶函数的内联说明:
1、函数本身,也就是“costs()”被内联到调用处
2、函数的函数参数,也就是“block:()”,本质上是“println(“Hello, Kotlin!!!”)”被内联到调用处
注意事项:
1、内联可能导致生成的代码增加;不过如果我们使用得当(即避免内联过大函数),性能上会有所提升,尤其是在循环中的“超多态(megamorphic)”调用处。
2、public/protected修饰的内联方法只能访问对应类的public成员;
3、内联函数的内联函数参数不能够被储存(赋值给变量);
4、内联函数的内联函数参数只能传递给其他内联函数参数。
5、上面2、3、4三点简单来说,就是:public/protected只能访问public修饰的方法;内联只能访问内联;内联函数的参数不能够被存储。
题外话:
val mIntArray: Array<Int> = arrayOf(1,2,3,4,5,6)
mIntArray.forEach {
if (it == 4){
println("找到了目标:$it")
//小细节:这里“[email protected]”仅仅是当it==4时,返回到“forEach”处继续执行,只是不执行“forEach”这条语句。
[email protected]
}
println("$it")
}
//上面的实现等价于下面的写法:
for (i in mIntArray) {
if (i == 4){
println("找到了目标:$i")
//小细节:这里“[email protected]”仅仅是当it==4时,返回到“forEach”处继续执行,只是不执行“forEach”这条语句。
continue
}
println("i = $i")
}
二者运行挤过如下:
现在我们把上面for循环里面的“continue”关键字改为“break”关键字,然后再运行:
for (i in mIntArray) {
if (i == 4){
println("找到了目标:$i")
//小细节:这里“[email protected]”仅仅是当it==4时,返回到“forEach”处继续执行,只是不执行“forEach”这条语句。
break
}
println("i = $i")
}
结果如下: