天天看點

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學習筆記十九、内聯函數