Kotlin中label标签的使用

以下内容参考这篇文章,仅做记录:
http://www.liying-cn.net/kotlin/docs/reference/returns.html

你可能会好奇,对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, "手机号不能为空")
                return@setOnClickListener
            }
            if (!ValidateUtils.isMobile(phone)) {
                ToastUtils.showShortToast(this, "请输入正确手机号")
                return@setOnClickListener
            }
            if (TextUtils.isEmpty(password)) {
                ToastUtils.showShortToast(this, "密码不能为空")
                return@setOnClickListener
            }
            if (password.length < 6 || password.length > 16) {
                ToastUtils.showShortToast(this, "请输入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, "请输入6-16位密码")
                return@setOnClickListener
            }

这个@setOnClickListener是个什么鬼呢?
其实我们被编译器的颜色误导了,这个@标记的是return,也就是 return@

Kotlin的返回与跳转

Kotlin 中存在 3 种跳出程序流程的表达式:

  • return. 默认行为是, 从最内层的函数或 匿名函数 中返回.
  • break. 结束最内层的循环.
  • continue. 在最内层的循环中, 跳转到下一次循环.

所有这些表达式都可以用作更大的表达式的一部分:

val s = person.name ?: return

这些表达式的类型都是 Nothing 类型.

Break 和 Continue 的位置标签

Kotlin 中的任何表达式都可以用 label 标签来标记. 标签由标识符后面加一个 @ 符号构成, 比如: abc@, fooBar@ 都是合法的标签(参见 语法). 要给一个表达式标记标签, 我们只需要将标签放在它之前:

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

然后, 我们就可以使用标签来限定 break 或 continue 的跳转对象:

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

通过标签限定后, break 语句, 将会跳转到这个标签标记的循环语句之后. continue 语句则会跳转到循环语句的下一次循环.

使用标签控制 return 的目标

在 Kotlin 中, 通过使用字面值函数(function literal), 局部函数(local function), 以及对象表达式(object expression), 允许实现函数的嵌套. 通过标签限定的 return 语句, 可以从一个外层函数中返回. 最重要的使用场景是从 Lambda 表达式中返回. 回忆一下我们曾经写过以下代码:

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

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

这里的 return 会从最内层的函数中返回, 也就是, 从 foo 函数返回. (注意, 这种非局部的返回(non-local return), 仅对传递给 内联函数(inline function) 的 Lambda 表达式有效.) 如果需要从 Lambda 表达式返回, 我们必须对它标记一个标签, 然后使用这个标签来指明 return 的目标:

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // 局部的返回(local return), 返回到 Lambda 表达式的调用者, 也就是, 返回到 forEach 循环
        print(it)
    }
    print(" done with explicit label")
}
//sampleEnd

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

这样, return 语句就只从 Lambda 表达式中返回. 通常, 使用隐含标签会更方便一些, 隐含标签的名称与 Lambda 表达式被传递去的函数名称相同.

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // 局部的返回(local return), 返回到 Lambda 表达式的调用者, 也就是, 返回到 forEach 循环
        print(it)
    }
    print(" done with implicit label")
}
//sampleEnd

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

或者, 我们也可以使用 匿名函数 来替代 Lambda 表达式. 匿名函数内的 return 语句会从匿名函数内返回.

//sampleStart
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return  // 局部的返回(local return), 返回到匿名函数的调用者, 也就是, 返回到 forEach 循环
        print(value)
    })
    print(" done with anonymous function")
}
//sampleEnd

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

注意, 上面三个例子中局部返回的使用, 都与通常的循环中的 continue 关键字的使用很类似. 不存在与 break 直接等价的语法, 但可以模拟出来, 方法是增加一个嵌套的 Lambda 表达式, 然后在它内部使用非局部的返回:

//sampleStart
fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // 非局部的返回(non-local return), 从传递给 run 函数的 Lambda 表达式中返回
            print(it)
        }
    }
    print(" done with nested loop")
}
//sampleEnd

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

当 return 语句指定了返回值时, 源代码解析器会将这样的语句优先识别为使用标签限定的 return 语句, 也就是说:

return@a 1

含义是 “返回到标签 @a 处, 返回值为 1”, 而不是 “返回一个带标签的表达式 (@a 1)”.

最后

这下应该明白为什么要用return@setOnClickListener这种写法了吧,是为了指定返回的目标位置,如果直接写return,则会直接退出onCreate方法,导致下面的代码无法执行。

うずまき ナルト.jpeg

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容