Kotlin 高階函數與內聯函數

1、前言

<font face= 黑體>在 Kotlin 學習筆記以內置類型(2)中咱們已經將 Kotlin 函數的基本概念基本用法講完了,今天咱們來說函數進階java

2、高階函數

2.一、高階函數概念

<font face= 黑體>高階函數就是參數類型包含函數類型或者返回值類型是函數類型的函數,簡單的說,高階函數就是函數裏面套函數,以下所示:git

// 參數類型是函數類型
fun needsFunction(block: () -> Unit) {
    block()
}

// 返回值是函數類型
fun returnsFunction(): () -> Long {
    return {System.currentTimeMillis()}
}

2.二、常見的高階函數

  1. <font face= 黑體>forEach 函數: 接受的參數是一個函數github

    // Kotin 自帶的 forEach 函數
    inline fun IntArray.forEach(action: (Int) -> Unit): Unit {
        for (element in this) action(element)
    }
  2. <font face= 黑體>map 函數: 接受的參數是一個函數segmentfault

    // Kotin 自帶的 map 函數
    inline fun <R> IntArray.map(transform: (Int) -> R): List<R> {
        return mapTo(ArrayList<R>(size), transform)
    }

2.三、高階函數的調用

<font face= 黑體>forEach 的調用:數組

val intArray = IntArray(5){ it + 1 }

intArray.forEach(::println)

// 括號() 裏面其實能夠把它當作一個參數,只是這個參數是函數
intArray.forEach ({
    println(it)
})

// () 能夠省略,就變成了下面這樣
intArray.forEach {
    println(it)
}
<font face= 黑體>forEach 接受的類型參數類型是 (Int) -> Unit,而 println 函數的類型有一個就是 (Int) -> Unit,因此能夠用函數引用來接收。

3、內聯函數

3.一、內聯函數概念

<font face= 黑體>被 inline 標記的函數就是內聯函數,其原理就是:在編譯時期,把調用這個函數的地方用這個函數的方法體進行替換。咱們來看下面這個代碼,就是一個 forEach 函數遍歷數組:性能優化

val ints = intArrayOf(1, 2, 3, 4)
ints.forEach {
    println("Hello $it")
}

<font face= 黑體>forEach 函數的定義上面咱們已經看到了,以下,能夠看到,forEach 被 inline 修飾,因此它是個內聯函數函數

inline fun IntArray.forEach(action: (Int) -> Unit): Unit {
    for (element in this) action(element)
}

<font face= 黑體>其實 forEach 真正的實現是下面這個代碼:性能

for (element in this) action(element)

<font face= 黑體>內聯函數能夠減小函數的調用來優化性能。學習

3.二、內聯函數的定義

<font face= 黑體>內聯函數的定義很簡單,就是在一個函數的前面加上 inline 關鍵字。優化

inline fun hello() {
    println("hello")
}

<font face= 黑體>雖說內聯函數能夠減小函數的調用來優化性能,可是並非每一個函數前加一個 inline 就能夠優化性能,其實咱們通常會把高階函數定義爲內聯函數。

3.三、高階函數與內聯函數更配

cost {
    println("hello")
}
inline fun cost(block: () -> Unit) {
    val start = System.currentTimeMillis()
    block()
    println(System.currentTimeMillis() - start)
}

<font face= 黑體>好比說咱們要計算 println("hello") 這段代碼執行的時間,若是不加 inline 的話,那麼調用 cost 就要建立 Lambda 表達式,函數調用,結果發現這些操做的時間就要大於 println("hello") 這段代碼執行的時間,這樣是徹底沒有必要的,因此咱們加上 inline 以後,調用 println("hello"),實際上就等於下面這樣:

val start = System.currentTimeMillis()
println("hello")
println(System.currentTimeMillis() - start)
<font face= 黑體>能夠看到加上 inline 以後,cost 函數的調用開銷沒了,Lambda 表達式的建立開銷也沒了,這就是內聯函數的做用。

3.四、內聯函數的限制

  • <font face= 黑體>public/protected 的內聯方法只能訪問對應類的 public 成員;
  • <font face= 黑體>內聯函數裏面的參數不能被存儲(賦值給一個變量);
  • <font face= 黑體>內聯函數的參數只能傳遞給其餘內聯函數。
<font face= 黑體> 其實內聯函數最重要的是對高階函數的性能優化。

4、小結

<font face= 黑體>本篇博客主要講了 Kotlin 中的高階函數內聯函數,下一節咱們講 Kotin 的 集合變換與聚合

5、源碼

源碼 已上傳至 github,有須要能夠直接下載。

相關文章
相關標籤/搜索