Kotlin中l(wèi)abel標(biāo)簽的使用

以下內(nèi)容參考這篇文章,僅做記錄:
http://www.liying-cn.net/kotlin/docs/reference/returns.html

你可能會(huì)好奇张吉,對(duì)Kotlin中的一些用法感到困惑,比如:

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
     
        btn_login.setOnClickListener({
            val phone = et_phone.text.toString().trim()
            val password = et_password.text.toString().trim()
            if (TextUtils.isEmpty(phone)) {
                ToastUtils.showShortToast(this, "手機(jī)號(hào)不能為空")
                return@setOnClickListener
            }
            if (!ValidateUtils.isMobile(phone)) {
                ToastUtils.showShortToast(this, "請(qǐng)輸入正確手機(jī)號(hào)")
                return@setOnClickListener
            }
            if (TextUtils.isEmpty(password)) {
                ToastUtils.showShortToast(this, "密碼不能為空")
                return@setOnClickListener
            }
            if (password.length < 6 || password.length > 16) {
                ToastUtils.showShortToast(this, "請(qǐng)輸入6-16位密碼")
                return@setOnClickListener
            }
            getCampus(phone, password)
        })
        btn_forget_password.setOnClickListener({
            val phone = et_phone.text.toString().trim()
            startActivity(
                    Intent(this@LoginActivity, ForgetPasswordActivity::class.java).putExtra("phone",
                            phone))
        })
       

上面是我從登錄功能中截取的一段代碼,我們來著重看下面這句:

   if (password.length < 6 || password.length > 16) {
                ToastUtils.showShortToast(this, "請(qǐng)輸入6-16位密碼")
                return@setOnClickListener
            }

這個(gè)@setOnClickListener是個(gè)什么鬼呢?
其實(shí)我們被編譯器的顏色誤導(dǎo)了算色,這個(gè)@標(biāo)記的是return,也就是 return@

Kotlin的返回與跳轉(zhuǎn)

Kotlin 中存在 3 種跳出程序流程的表達(dá)式:

  • return. 默認(rèn)行為是, 從最內(nèi)層的函數(shù)或 匿名函數(shù) 中返回.
  • break. 結(jié)束最內(nèi)層的循環(huán).
  • continue. 在最內(nèi)層的循環(huán)中, 跳轉(zhuǎn)到下一次循環(huán).

所有這些表達(dá)式都可以用作更大的表達(dá)式的一部分:

val s = person.name ?: return

這些表達(dá)式的類型都是 Nothing 類型.

Break 和 Continue 的位置標(biāo)簽

Kotlin 中的任何表達(dá)式都可以用 label 標(biāo)簽來標(biāo)記. 標(biāo)簽由標(biāo)識(shí)符后面加一個(gè) @ 符號(hào)構(gòu)成, 比如: abc@, fooBar@ 都是合法的標(biāo)簽(參見 語法). 要給一個(gè)表達(dá)式標(biāo)記標(biāo)簽, 我們只需要將標(biāo)簽放在它之前:

loop@ for (i in 1..100) {
    // ...
}

然后, 我們就可以使用標(biāo)簽來限定 break 或 continue 的跳轉(zhuǎn)對(duì)象:

loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) break@loop
    }
}

通過標(biāo)簽限定后, break 語句, 將會(huì)跳轉(zhuǎn)到這個(gè)標(biāo)簽標(biāo)記的循環(huán)語句之后. continue 語句則會(huì)跳轉(zhuǎn)到循環(huán)語句的下一次循環(huán).

使用標(biāo)簽控制 return 的目標(biāo)

在 Kotlin 中, 通過使用字面值函數(shù)(function literal), 局部函數(shù)(local function), 以及對(duì)象表達(dá)式(object expression), 允許實(shí)現(xiàn)函數(shù)的嵌套. 通過標(biāo)簽限定的 return 語句, 可以從一個(gè)外層函數(shù)中返回. 最重要的使用場(chǎng)景是從 Lambda 表達(dá)式中返回. 回憶一下我們?cè)?jīng)寫過以下代碼:

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return // 非局部的返回(non-local return), 直接返回到 foo() 函數(shù)的調(diào)用者
        print(it)
    }
    println("this point is unreachable")
}
//sampleEnd

fun main(args: Array<String>) {
    foo()
}

這里的 return 會(huì)從最內(nèi)層的函數(shù)中返回, 也就是, 從 foo 函數(shù)返回. (注意, 這種非局部的返回(non-local return), 僅對(duì)傳遞給 內(nèi)聯(lián)函數(shù)(inline function) 的 Lambda 表達(dá)式有效.) 如果需要從 Lambda 表達(dá)式返回, 我們必須對(duì)它標(biāo)記一個(gè)標(biāo)簽, 然后使用這個(gè)標(biāo)簽來指明 return 的目標(biāo):

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // 局部的返回(local return), 返回到 Lambda 表達(dá)式的調(diào)用者, 也就是, 返回到 forEach 循環(huán)
        print(it)
    }
    print(" done with explicit label")
}
//sampleEnd

fun main(args: Array<String>) {
    foo()
}

這樣, return 語句就只從 Lambda 表達(dá)式中返回. 通常, 使用隱含標(biāo)簽會(huì)更方便一些, 隱含標(biāo)簽的名稱與 Lambda 表達(dá)式被傳遞去的函數(shù)名稱相同.

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // 局部的返回(local return), 返回到 Lambda 表達(dá)式的調(diào)用者, 也就是, 返回到 forEach 循環(huán)
        print(it)
    }
    print(" done with implicit label")
}
//sampleEnd

fun main(args: Array<String>) {
    foo()
}

或者, 我們也可以使用 匿名函數(shù) 來替代 Lambda 表達(dá)式. 匿名函數(shù)內(nèi)的 return 語句會(huì)從匿名函數(shù)內(nèi)返回.

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return  // 局部的返回(local return), 返回到匿名函數(shù)的調(diào)用者, 也就是, 返回到 forEach 循環(huán)
        print(value)
    })
    print(" done with anonymous function")
}
//sampleEnd

fun main(args: Array<String>) {
    foo()
}

注意, 上面三個(gè)例子中局部返回的使用, 都與通常的循環(huán)中的 continue 關(guān)鍵字的使用很類似. 不存在與 break 直接等價(jià)的語法, 但可以模擬出來, 方法是增加一個(gè)嵌套的 Lambda 表達(dá)式, 然后在它內(nèi)部使用非局部的返回:

//sampleStart
fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // 非局部的返回(non-local return), 從傳遞給 run 函數(shù)的 Lambda 表達(dá)式中返回
            print(it)
        }
    }
    print(" done with nested loop")
}
//sampleEnd

fun main(args: Array<String>) {
    foo()
}

當(dāng) return 語句指定了返回值時(shí), 源代碼解析器會(huì)將這樣的語句優(yōu)先識(shí)別為使用標(biāo)簽限定的 return 語句, 也就是說:

return@a 1

含義是 “返回到標(biāo)簽 @a 處, 返回值為 1”, 而不是 “返回一個(gè)帶標(biāo)簽的表達(dá)式 (@a 1)”.

最后

這下應(yīng)該明白為什么要用return@setOnClickListener這種寫法了吧螟够,是為了指定返回的目標(biāo)位置灾梦,如果直接寫return,則會(huì)直接退出onCreate方法齐鲤,導(dǎo)致下面的代碼無法執(zhí)行斥废。

うす?まき ナルト.jpeg

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末椒楣,一起剝皮案震驚了整個(gè)濱河市给郊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捧灰,老刑警劉巖淆九,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異毛俏,居然都是意外死亡炭庙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門煌寇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焕蹄,“玉大人,你說我怎么就攤上這事阀溶∧逶啵” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵银锻,是天一觀的道長(zhǎng)永品。 經(jīng)常有香客問我,道長(zhǎng)击纬,這世上最難降的妖魔是什么鼎姐? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上炕桨,老公的妹妹穿的比我還像新娘饭尝。我一直安慰自己,他們只是感情好献宫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布芋肠。 她就那樣靜靜地躺著,像睡著了一般遵蚜。 火紅的嫁衣襯著肌膚如雪帖池。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天吭净,我揣著相機(jī)與錄音睡汹,去河邊找鬼。 笑死寂殉,一個(gè)胖子當(dāng)著我的面吹牛囚巴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播友扰,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼彤叉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了村怪?” 一聲冷哼從身側(cè)響起秽浇,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甚负,沒想到半個(gè)月后柬焕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梭域,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年斑举,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片病涨。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡富玷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出既穆,到底是詐尸還是另有隱情赎懦,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布循衰,位于F島的核電站铲敛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏会钝。R本人自食惡果不足惜伐蒋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一工三、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧先鱼,春花似錦俭正、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宏多,卻和暖如春儿惫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背伸但。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工肾请, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人更胖。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓铛铁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親却妨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饵逐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 前言 人生苦多,快來 Kotlin 彪标,快速學(xué)習(xí)Kotlin倍权! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,208評(píng)論 9 118
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,148評(píng)論 0 13
  • 第2章 Kotlin 語法基礎(chǔ) 人與人之間通過語言來交流溝通,互相協(xié)作淳蔼。人與計(jì)算機(jī)之間怎樣“交流溝通”呢乡范?答案是編...
    光劍書架上的書閱讀 1,615評(píng)論 0 6
  • 如果遠(yuǎn)妹分到任意1/4區(qū) 科:星巴克 龍:一點(diǎn)點(diǎn) 蟒:奈雪 胖:喜茶
    初夏夏初閱讀 342評(píng)論 0 0
  • 柳哲 晨起披讀先祖、元代大儒柳貫詩文集生年,其中有詩句“吾門不貴奢婴程,喪祭當(dāng)從禮”、“朝飡猶一飽抱婉,不愧在家貧”档叔,頗得我心...
    柳志儒閱讀 364評(píng)論 0 0