Kotlin Reference: Returns and Jumps

  Kotlin 有三种结构跳转表达式:

  • return:默认返回最近一层的函数或匿名函数
  • break:结束最近一层的循环。
  • continue:进行到最近一层循环的下一步。

  这三个表达式都可以用在其他表达式中,如:

[code lang=”kotlin”]val s = person.name ?: return[/code]

  以上三个表达式的类型为 Nothing 。【注】Nothing 类型是一个特殊的类型,它没有实际的值,只是用来标记返回或不可能执行到的位置(如抛出异常)。

Break and Continue Labels

  可以为 Kotlin 中的任意表达式添加标签,标签的形式为标识符后加 @ 符号,如 abc@fooBar@ 等(详见 Grammar)。只需把标签放在表达式前面,即可为表达式添加标签:

[code lang=”kotlin”]loop@ for (i in 1..100) {
// …
}[/code]

  现在,我们就可以通过标签来限定 breakcontinue

[code lang=”kotlin”]loop@ for (i in 1..100) {
for (j in 1..100) {
if (…) break@loop
}
}[/code]

  使用标签限定的 break 会让程序跳转到标签对应的循环的后面(【注】即跳出该循环),continue 则会继续执行该循环的下一步迭代。

Return at Labels

  Kotlin 中的函数可以通过函数字面值、局部函数和对象表达式(Object Expression)等方式进行嵌套,通过标签限定的 return 可以直接让外部函数返回。这种用法最重要的用途是从 Lambda 中返回,比如当我们这样写:

[code lang=”kotlin”]fun foo() {
ints.forEach {
if (it == 0) return
print(it)
}
}[/code]

上面代码中的 return 会返回最近一层的函数,也就是 foo()。(注意此类非局部的 return 仅可用于传递给内联函数的 Lambda 表达式。)

  如果想要让 Lambda 表达式返回,则必须为其添加标签,并使用标签限定的 return

[code lang=”kotlin”]fun foo() {
ints.forEach lit@ {
if (it == 0) return@lit
print(it)
}
}[/code]

现在,上面代码中的 return 就只会让 Lambda 表达式返回。通常使用隐式的标签会更方便:隐式标签和接受 lambda 表达式的函数同名:

[code lang=”kotlin”]fun foo() {
ints.forEach {
if (it == 0) return@forEach
print(it)
}
}[/code]

【注】上面的代码中,希望让传给 ints.forEach 的 Lambda 表达式返回,可以直接使用 @forEach 标签而不必手动标记其位置。

  此外,还可以使用匿名函数代替 Lambda 表达式,匿名函数中的 return 会让匿名函数本身返回:

[code lang=”kotlin”]fun foo() {
ints.forEach(fun(value: Int) {
if (value == 0) return
print(value)
})
}[/code]

【注】上面的代码中,return 返回的是匿名函数 fun(value: Int),而不是外层的 foo()

【注】在 Kotlin 中,未限定的 return 只能用于退出一个命名或匿名函数;如果想要退出 Lambda,就必须使用标签。但如果 Lambda 传递到的函数是内联的,则 Lambda 中的 return 也会被内联,所以此时允许使用 return

  当标签和返回值同时出现在 return 后面时,分词器会优先标签限定的返回(【注】即 return 会优先结合标签,构成带标签限定的返回),如:

[code lang=”kotlin”]return@a 1[/code]

表示“在 @a 标签处返回 1”,而不是“返回一个带有标签的表达式 (@a 1)”。