Kotlin基礎學習之lambda中return語句詳解
前言
當我們愛上lambda并且大范圍使用它的時候,我想大家都會被lambda中的return語句狠狠地調戲過,所以今天我們需要一起來揭開lambda中return的神秘面紗。
首先來看一個例子:
fun demo() {
val indexes = arrayOf(1, 2, 3, 4, 5, 6, 7)
indexes.forEach {
if (it > 5) {
return
}
println(it)
}
println("End")
}
按照我們的預期,調用demo后,它應該輸出:
1
2
3
4
5
End
事實真是如此嗎?大家可以運行一下上面的代碼,它的實際輸出是:
1
2
3
4
5
什么鬼?那個End被運行時給偷吃了嗎?不是,為了說明其中的緣由,讓我們看一下forEach的定義:
public inline fun <T> Array<out T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
從定義中,我們可以看到forEach函數被定義為了內聯(lián)函數,而根據帶有l(wèi)ambda的內聯(lián)函數處理機制(相關講解可參考:Kotlin:關于內聯(lián)函數的一些理解),我們的demo因為被內聯(lián)最終會被編譯為:
fun demo() {
val indexes = arrayOf(1, 2, 3, 4, 5, 6, 7)
for (element in indexes) {
if (element > 5) {
return
}
println(element)
}
println("End")
}
從最終編譯后的代碼中我們可以很清楚的發(fā)現,最后的End不是被偷吃了,而是因為demo函數在判斷條件滿足的情況下提前返回了,這樣的return用高端一點的語句就叫做:非局部返回。
如果我們想要return從forEach(即lambda)中返回怎么辦?讓我們先改造一下上面對forEach的調用:
indexes.forEach {
if (it > 5) {
return@forEach
}
println(it)
}
再次運行一下 demo:
1
2
3
4
5
End
這個時候的輸出就跟我們的預期一樣了,很神奇對不對?我們只要在return后面加一個@forEach就可以了,這就是所謂標簽返回(或局部返回),其完整的語法如下:
indexes.forEach label@ {
if (it > 5) {
return@label
}
println(it)
}
如果我們省略forEach后面label的定義,那么默認的label就是把lambda作為參數的函數名(這里是forEach)。
這就是lambda中return語句的所有內容,很簡單是不是?接下來就是盡情玩耍的時間了?別著急,這里還有一些注意事項,比如:
fun doSomething(action: () -> Unit) {
action()
}
inline fun doOtherThing(action: () -> Unit) {
action()
}
fun main(args: Array<String>) {
doSomething {
return
}
}
fun main(args: Array<String>) {
var action = {
return
}
doOtherThing(action)
}
運行上面的例子會得到怎樣的輸出?不好意思,這個調用會因為編譯失敗不給你運行的機會,
通過上面的討論我們知道,非局部返回是從lambda調用點所在的函數中返回,所以這就要求我們lambda中的return語句只能出現在內聯(lián)函數且該lambda表達式以參數形式直接傳遞給該函數的情況,其他情況不允許則是因為lambda可以綁定給一個變量以便在函數返回后繼續(xù)使用(比如閉包),而這個時候的return已經為時已晚。
好了,關于lambda控制流的內容就討論到這里了,最后祝愿大家快樂coding ^ _ ^
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
android onTouchEvent處理機制總結(必看)
下面小編就為大家?guī)硪黄猘ndroid onTouchEvent處理機制總結(必看)小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Android中Serializable和Parcelable序列化對象詳解
這篇文章主要介紹了Android中Serializable和Parcelable序列化對象的相關資料,感興趣的小伙伴們可以參考一下2016-02-02
Android getReadableDatabase() 和 getWritableDatabase()分析對比
這篇文章主要介紹了Android getReadableDatabase() 和 getWritableDatabase()分析對比的相關資料,需要的朋友可以參考下2017-06-06
Android 使用SwipeRefreshLayout控件仿抖音做的視頻下拉刷新效果
這篇文章主要介紹了Android 使用SwipeRefreshLayout控件仿抖音做的視頻下拉刷新效果,需要的朋友可以參考下2018-05-05

