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]
现在,我们就可以通过标签来限定 break
和 continue
:
[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)
”。