天天看点

Kotlin学习笔记十九、内联函数

原因/定义:

使用高阶函数会带来一些运行时的效率损失:每一个函数都是一个对象,并且会捕获一个闭包;即那些在函数体内会访问到的变量;内存分配(对于函数对象和类)和虚拟调用会引入运行时间开销。但是在许多情况下通过“内联化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")
}
           

二者运行挤过如下:

Kotlin学习笔记十九、内联函数

现在我们把上面for循环里面的“continue”关键字改为“break”关键字,然后再运行:

for (i in mIntArray) {
        if (i == 4){
            println("找到了目标:$i")
            //小细节:这里“[email protected]”仅仅是当it==4时,返回到“forEach”处继续执行,只是不执行“forEach”这条语句。
            break
        }
        println("i = $i")
    }
           

结果如下:

Kotlin学习笔记十九、内联函数