天天看點

Kotlin-23-inline+noinline+crossinline

目錄

1、inline 背景

2、inline 原理

3、noinline

4、crossinline

5、注意

1、inline 背景

inline---内聯函數

當我們在使用高階函數的時候,因為除了高階函數本身是個函數以外,它的參數或者傳回值也是一個Lambda函數,lambda函數内部還有局部變量,當在編譯運作的時候,因為每一個Lambda函數都是一個對象,并且還會捕獲一個閉包及閉包内會通路到的變量。 這樣在記憶體配置設定(對于函數對象和類)和虛拟機調用上都會加大運作時間開銷。

為了解決高階函數所帶來的額外開銷,kotlin加入了inline關鍵字。

注意:過多的使用inline關鍵字會對編譯器造成很大的性能壓力,是以我們建議隻在高階函數中使用inline關鍵字。

2、inline 原理

代碼在編譯以後,會将内聯函數的函數體複制到調用處。

下面左邊是我們的inline函數,右邊是我們編譯後的class檔案。

從編譯後的class可以看出,inline的函數體會被直接複制到調用該内聯函數的地方。

Kotlin-23-inline+noinline+crossinline
Kotlin-23-inline+noinline+crossinline

3、noinline

因為inline是用來修飾高階函數的,又因為被inline修飾的高階函數,其參數中的lambda函數也會隐式變成inline函數,但如果我們不想要将lambda參數内聯化的話,就可以使用noline關鍵字。

下面左邊是kotlin代碼,右邊是編譯後的class檔案,綠色框中,就是我們内聯化的 lambda函數a,紅色就是沒有被内聯化的lambda函數b。

Kotlin-23-inline+noinline+crossinline
Kotlin-23-inline+noinline+crossinline

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 表達式中目前還不可用。