在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ Kotlin lambda表達(dá)式
Kotlin內(nèi)聯(lián)函數(shù)
Kotlin開發(fā)環(huán)境設(shè)置(Eclipse)
Kotlin調(diào)用Java代碼
Kotlin使用Ant
Kotlin編譯器插件
Kotlin相等性
Kotlin JavaScript模塊
編寫Kotlin代碼文檔
Kotlin返回和跳轉(zhuǎn)
Kotlin異常處理
Kotlin可見性修飾符
Kotlin委托
Kotlin委托屬性
Kotlin編碼約定/編碼風(fēng)格
Kotlin基礎(chǔ)語法
使用Kotlin進行服務(wù)器端開發(fā)
Kotlin接口
Kotlin反射
Kotlin類型別名
Kotlin枚舉類
Kotlin當(dāng)前版本是多少?
Kotlin注解處理工具
Kotlin類型的檢查與轉(zhuǎn)換
Kotlin屬性和字段
Kotlin類型安全的構(gòu)建器
Kotlin相比Java語言有哪些優(yōu)點?
Kotlin JavaScript反射
Kotlin 是什么?
Kotlin泛型
Kotlin慣用語法
Kotlin與OSGi
Kotlin數(shù)據(jù)類型
Kotlin是面向?qū)ο筮€是函數(shù)式語言?
Kotlin動態(tài)類型
Kotlin協(xié)程
Kotlin操作符符重載
Kotlin使用Gradle
Kotlin密封類
Kotlin兼容性
Kotlin集合
Kotlin調(diào)用JavaScript
Kotlin null值安全
Kotlin函數(shù)
Kotlin開發(fā)環(huán)境設(shè)置(IntelliJ IDEA)
Kotlin嵌套類
Kotlin控制流程
Kotlin和Java語言比較
Kotlin 與 Java 語言兼容嗎?
Kotlin教程
Kotlin類和繼承
Kotlin對象表達(dá)式和對象聲明
JavaScript中調(diào)用Kotlin
Kotlin區(qū)間/范圍
Kotlin數(shù)據(jù)類
Kotlin lambda表達(dá)式
Kotlin是免費的嗎?
Kotlin包
使用Kotlin進行Android開發(fā)
在Java中調(diào)用Kotlin代碼
Kotlin this表達(dá)式
使用Kotlin進行JavaScript開發(fā)
Kotlin擴展
Kotlin解構(gòu)聲明
Kotlin注解
Kotlin使用Maven

Kotlin lambda表達(dá)式

高階函數(shù)和 lambda 表達(dá)式

高階函數(shù)

高階函數(shù)是將函數(shù)用作參數(shù)或返回值的函數(shù)。
這種函數(shù)的一個很好的例子是 lock(),它接受一個鎖對象和一個函數(shù),獲取鎖,運行函數(shù)并釋放鎖:

fun <T> lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
        return body()
    }
    finally {
        lock.unlock()
    }
}

讓我們來檢查上面的代碼:body 擁有函數(shù)類型() -> T
所以它應(yīng)該是一個不帶參數(shù)并且返回 T 類型值的函數(shù)。
它在 try{: .keyword }-代碼塊內(nèi)部調(diào)用、被 lock 保護,其結(jié)果由lock()函數(shù)返回。

如果我們想調(diào)用 lock() 函數(shù),我們可以把另一個函數(shù)傳給它作為參數(shù)(參見函數(shù)引用):

fun toBeSynchronized() = sharedResource.operation()

val result = lock(lock, ::toBeSynchronized)

通常會更方便的另一種方式是傳一個 lambda 表達(dá)式

val result = lock(lock, { sharedResource.operation() })

Lambda 表達(dá)式在下文會有更詳細(xì)的描述,但為了繼續(xù)這一段,下面來看看一個簡短的概述:

  • lambda 表達(dá)式總是被大括號括著,
  • 其參數(shù)(如果有的話)在 -> 之前聲明(參數(shù)類型可以省略),
  • 函數(shù)體(如果存在的話)在 -> 后面。

在 Kotlin 中有一個約定,如果函數(shù)的最后一個參數(shù)是一個函數(shù),并且你傳遞一個 lambda 表達(dá)式作為相應(yīng)的參數(shù),你可以在圓括號之外指定它:

lock (lock) {
    sharedResource.operation()
}

高階函數(shù)的另一個例子是 map()

fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
    val result = arrayListOf<R>()
    for (item in this)
        result.add(transform(item))
    return result
}

該函數(shù)可以如下調(diào)用:

val doubled = ints.map { value -> value * 2 }

請注意,如果 lambda 是該調(diào)用的唯一參數(shù),則調(diào)用中的圓括號可以完全省略。

it:單個參數(shù)的隱式名稱

另一個有用的約定是,如果函數(shù)字面值只有一個參數(shù),
那么它的聲明可以省略(連同 ->),其名稱是 it

ints.map { it * 2 }

這些約定可以寫LINQ-風(fēng)格的代碼:

strings.filter { it.length == 5 }.sortBy { it }.map { it.toUpperCase() }

下劃線用于未使用的變量(自 1.1 起)

如果 lambda 表達(dá)式的參數(shù)未使用,那么可以用下劃線取代其名稱:

map.forEach { _, value -> println("$value!") }

在 lambda 表達(dá)式中解構(gòu)(自 1.1 起)

在 lambda 表達(dá)式中解構(gòu)是作為解構(gòu)聲明)的一部分描述的。

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

使用內(nèi)聯(lián)函數(shù)有時能提高高階函數(shù)的性能。

Lambda 表達(dá)式和匿名函數(shù)

一個 lambda 表達(dá)式或匿名函數(shù)是一個“函數(shù)字面值”,即一個未聲明的函數(shù),
但立即做為表達(dá)式傳遞??紤]下面的例子:

max(strings, { a, b -> a.length < b.length })

函數(shù) max 是一個高階函數(shù),換句話說它接受一個函數(shù)作為第二個參數(shù)。
其第二個參數(shù)是一個表達(dá)式,它本身是一個函數(shù),即函數(shù)字面值。寫成函數(shù)的話,它相當(dāng)于

fun compare(a: String, b: String): Boolean = a.length < b.length

函數(shù)類型

對于接受另一個函數(shù)作為參數(shù)的函數(shù),我們必須為該參數(shù)指定函數(shù)類型。
例如上述函數(shù) max 定義如下:

fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? {
    var max: T? = null
    for (it in collection)
        if (max == null || less(max, it))
            max = it
    return max
}

參數(shù) less 的類型是 (T, T) -> Boolean,即一個接受兩個類型T的參數(shù)并返回一個布爾值的函數(shù):
如果第一個參數(shù)小于第二個那么該函數(shù)返回 true。

在上面第 4 行代碼中,less 作為一個函數(shù)使用:通過傳入兩個 T 類型的參數(shù)來調(diào)用。

如上所寫的是就函數(shù)類型,或者可以有命名參數(shù),如果你想文檔化每個參數(shù)的含義的話。

val compare: (x: T, y: T) -> Int = ……

Lambda 表達(dá)式語法

Lambda 表達(dá)式的完整語法形式,即函數(shù)類型的字面值如下:

val sum = { x: Int, y: Int -> x + y }

lambda 表達(dá)式總是被大括號括著,
完整語法形式的參數(shù)聲明放在括號內(nèi),并有可選的類型標(biāo)注,
函數(shù)體跟在一個 -> 符號之后。如果推斷出的該 lambda 的返回類型不是 Unit,那么該 lambda 主體中的最后一個(或可能是單個)表達(dá)式會視為返回值。

如果我們把所有可選標(biāo)注都留下,看起來如下:

val sum: (Int, Int) -> Int = { x, y -> x + y }

一個 lambda 表達(dá)式只有一個參數(shù)是很常見的。
如果 Kotlin 可以自己計算出簽名,它允許我們不聲明唯一的參數(shù),并且將隱含地
為我們聲明其名稱為 it

ints.filter { it > 0 } // 這個字面值是“(it: Int) -> Boolean”類型的

我們可以使用限定的返回語法從 lambda 顯式返回一個值。否則,將隱式返回最后一個表達(dá)式的值。因此,以下兩個片段是等價的:

ints.filter {
    val shouldFilter = it > 0 
    shouldFilter
}

ints.filter {
    val shouldFilter = it > 0 
    return@filter shouldFilter
}

請注意,如果一個函數(shù)接受另一個函數(shù)作為最后一個參數(shù),lambda 表達(dá)式參數(shù)可以在
圓括號參數(shù)列表之外傳遞。
參見 callSuffix 的語法。

匿名函數(shù)

上面提供的 lambda 表達(dá)式語法缺少的一個東西是指定函數(shù)的返回類型的
能力。在大多數(shù)情況下,這是不必要的。因為返回類型可以自動推斷出來。然而,如果
確實需要顯式指定,可以使用另一種語法: 匿名函數(shù) 。

fun(x: Int, y: Int): Int = x + y

匿名函數(shù)看起來非常像一個常規(guī)函數(shù)聲明,除了其名稱省略了。其函數(shù)體
可以是表達(dá)式(如上所示)或代碼塊:

fun(x: Int, y: Int): Int {
    return x + y
}

參數(shù)和返回類型的指定方式與常規(guī)函數(shù)相同,除了
能夠從上下文推斷出的參數(shù)類型可以省略:

ints.filter(fun(item) = item > 0)

匿名函數(shù)的返回類型推斷機制與正常函數(shù)一樣:對于具有表達(dá)式函數(shù)體的匿名函數(shù)將自動
推斷返回類型,而具有代碼塊函數(shù)體的返回類型必須顯式
指定(或者已假定為 Unit)。

請注意,匿名函數(shù)參數(shù)總是在括號內(nèi)傳遞。 允許將函數(shù)
留在圓括號外的簡寫語法僅適用于 lambda 表達(dá)式。

Lambda表達(dá)式和匿名函數(shù)之間的另一個區(qū)別是
非局部返回的行為。一個不帶標(biāo)簽的 return{: .keyword } 語句
總是在用 fun{: .keyword } 關(guān)鍵字聲明的函數(shù)中返回。這意味著 lambda 表達(dá)式中的 return{: .keyword }
將從包含它的函數(shù)返回,而匿名函數(shù)中的 return{: .keyword }
將從匿名函數(shù)自身返回。

閉包

Lambda 表達(dá)式或者匿名函數(shù)(以及局部函數(shù)對象表達(dá)式)
可以訪問其 閉包 ,即在外部作用域中聲明的變量。 與 Java 不同的是可以修改閉包中捕獲的變量:

var sum = 0
ints.filter { it > 0 }.forEach {
    sum += it
}
print(sum)

帶接收者的函數(shù)字面值

Kotlin 提供了使用指定的 接收者對象 調(diào)用函數(shù)字面值的功能。
在函數(shù)字面值的函數(shù)體中,可以調(diào)用該接收者對象上的方法而無需任何額外的限定符。
這類似于擴展函數(shù),它允你在函數(shù)體內(nèi)訪問接收者對象的成員。
其用法的最重要的示例之一是類型安全的 Groovy-風(fēng)格構(gòu)建器

這樣的函數(shù)字面值的類型是一個帶有接收者的函數(shù)類型:

sum : Int.(other: Int) -> Int

該函數(shù)字面值可以這樣調(diào)用,就像它是接收者對象上的一個方法一樣:

1.sum(2)

匿名函數(shù)語法允許你直接指定函數(shù)字面值的接收者類型
如果你需要使用帶接收者的函數(shù)類型聲明一個變量,并在之后使用它,這將非常有用。

val sum = fun Int.(other: Int): Int = this + other

當(dāng)接收者類型可以從上下文推斷時,lambda 表達(dá)式可以用作帶接收者的函數(shù)字面值。

class HTML {
    fun body() { …… }
}

fun html(init: HTML.() -> Unit): HTML {
    val html = HTML()  // 創(chuàng)建接收者對象
    html.init()        // 將該接收者對象傳給該 lambda
    return html
}


html {       // 帶接收者的 lambda 由此開始
    body()   // 調(diào)用該接收者對象的一個方法
}