高階函數(shù)與內(nèi)聯(lián)函數(shù)

高階函數(shù)指以另一個(gè)函數(shù)或 lambda 表達(dá)式為參數(shù)或返回值類型的函數(shù)

調(diào)用時(shí)與調(diào)用普通函數(shù)一樣。

fun main(args: Array<String>) {
    test { println("aaa${it}") }
}
// 聲明 a 為函數(shù)類型
fun test(a:(Int)->Unit){
    a(11) // 調(diào)用 a 函數(shù)
}

作為返回值

需要指定函數(shù)類型作為返回值類型。下例中 test 函數(shù)聲明了一個(gè)函數(shù)類型做為返回值 —— 該函數(shù)接收 Int 類型參數(shù),并返回 String。因此 test(1) 后可以直接使用 () 調(diào)用返回的函數(shù)。

fun main(args: Array<String>) {
    println(test(1)(222)) // a = 222
    println(test(3)(333)) // else
}

fun test(a:Int):(Int)->String{
    return when(a){
        1-> {a:Int->"a = ${a}"}
        else->{b:Int->"else"}
    }
}

內(nèi)聯(lián)函數(shù)

使用 inline 修飾的函數(shù)是內(nèi)聯(lián)函數(shù) —— 函數(shù)體會被替換到函數(shù)被調(diào)用的地方,而不是正常的調(diào)用

  1. 內(nèi)聯(lián)時(shí),內(nèi)聯(lián)函數(shù)和已知具體內(nèi)容的 lambda 都會被內(nèi)聯(lián)。

  2. 函數(shù)的聲明不會被復(fù)制,只復(fù)制函數(shù)的函數(shù)體內(nèi)容。在 java 中也不可能在一個(gè)函數(shù)內(nèi)部定義另一個(gè)函數(shù)。

如下面定義了一個(gè)內(nèi)聯(lián)函數(shù) sync 以及其使用函數(shù) foo:

// 使用 inline 聲明一個(gè)內(nèi)聯(lián)函數(shù)
inline fun <T> synchronized(lock: Lock, action: () -> T): T {
            lock.lock()
            try {
                return action()
          }
          finally {
                lock.unlock()
          }
}
// 內(nèi)聯(lián)函數(shù)的使用者
fun foo(l: Lock) {
    println("Before sync")
    synchronized(l) {
        println("Action")
    }
    println("After sync")
}

其編譯后的代碼如下:

編譯后的代碼

可以發(fā)現(xiàn)將 sync 函數(shù)中的內(nèi)容完全復(fù)制到調(diào)用的地方,包括傳給 sync 的 lambda 表達(dá)式的內(nèi)容也內(nèi)聯(lián)到調(diào)用者中。

說明

在上述代碼中,調(diào)用 sync 時(shí),lambda 表達(dá)式的內(nèi)容是已知的,所以可以將表達(dá)式與 sync 函數(shù)一起被內(nèi)聯(lián)。

但如果調(diào)用內(nèi)聯(lián)函數(shù)時(shí),不知道 lambda 的具體內(nèi)容,則只能內(nèi)聯(lián)內(nèi)聯(lián)函數(shù) —— 即只復(fù)制 sync 函數(shù)的內(nèi)容,無法復(fù)制 lambda 的內(nèi)容。如下,調(diào)用 sync 時(shí)只是復(fù)制了 sync 的代碼,其中 lambda 表達(dá)式的內(nèi)容并沒有復(fù)制,這是因?yàn)樵谡{(diào)用時(shí)無法確定表達(dá)式的具體內(nèi)容:

class LockOwner(val lock: Lock) {
    fun runUnderLock(body: () -> Unit) {
        synchronized(lock, body)
    }
}

class LockOwner(val lock: Lock) {
    fun __runUnderLock__(body: () -> Unit) {
        lock.lock()
        try {
            body() // body 是外界傳入的,無法確定內(nèi)容,所以此處不復(fù)制 body 的內(nèi)容
        } finally {
            lock.unlock()
        }
    }
}

內(nèi)聯(lián)限制

并不是所有的 lambda 表達(dá)式都可以被內(nèi)聯(lián)。

  1. 如果 lambda 表達(dá)式在某個(gè)地方被保存起來,以便后面繼續(xù)使用,表達(dá)式則不能被內(nèi)聯(lián)。同時(shí)會提示 Illegal usage of inline-parameter.。

  2. 可以使用 noinline 修飾 lambda 參數(shù),以表示該 lambda 不進(jìn)行內(nèi)聯(lián)。

內(nèi)聯(lián)使用

  1. 內(nèi)聯(lián)函數(shù)只能提升帶有 lambda 參數(shù)的函數(shù)的性能。對于其余的函數(shù),內(nèi)聯(lián)無能為力。

  2. 內(nèi)聯(lián)函數(shù)必須非常小。如果函數(shù)很大,那么將函數(shù)復(fù)制到各個(gè)調(diào)用點(diǎn),將會極大增加字節(jié)碼的長度。


匿名函數(shù)

匿名函數(shù)與普通函數(shù)相似,除了 省略函數(shù)名及參數(shù)類型。

  1. 匿名函數(shù)的 return 語句從匿名函數(shù)中返回,而不是從包含匿名函數(shù)的函數(shù)中返回。

  2. return 從最近使用 fun 關(guān)鍵字聲明的函數(shù)返回。因此,匿名函數(shù)的 return 返回匿名函數(shù),而 lambda 表達(dá)式的 return 返回調(diào)用 return 的函數(shù)。

return 語法
  1. 匿名函數(shù)是 lambda 的另一種語法。因此,lambda 被內(nèi)聯(lián)時(shí)的限制一樣適用于匿名函數(shù)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容