我来学Kotlin-基础之返回值与跳转

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

  • return默认从最近的函数或者匿名函数返回,后面的代码不再执行
  • break跳出break最近的一个循环
  • continue忽略后面的代码,跳转到下一个步骤

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

1
val s = person.name ?: return

这个表达式的类型是Nothing类型

break和continue标签

在Kotlin里所有的表达式都可以用一个标签(label)来标记。标签由一个合法的标识符跟上一个@符号缓存,例如:abc@, fooBar@都是合法的标签。要标记一个表达式,只需要把标签放在表达式前面即可:

1
2
3
4
5
6
loop@ for (i in 1..10) {
for (j in 1..10) {
if (j > 5) break@loop
println("i, j = $i, $j")
}
}

上面这段代码的输出如下:

1
2
3
4
5
i, j = 1, 1
i, j = 1, 2
i, j = 1, 3
i, j = 1, 4
i, j = 1, 5

如果没有loop标签,那么break的行为是跳出里面一层的循环,输出结果还会有i, j = 2, 1等等,加了标签后直接跳出到最外层的循环。而continue是返回到标签处继续下一次的循环,下面的代码中带标签的continue和不带标签的break作用是一样的:

1
2
3
4
5
6
7
8
9
10
11
12
abc@ for (i in 1..4) {
for (j in 1..4) {
if (j > 2) continue@abc
println("i, j = $i, $j")
}
}
for (i in 1..4) {
for (j in 1..4) {
if (j > 2) break
println("i, j = $i, $j")
}
}

return

关键字return跟Java的差不多,但是功能要复杂一些,个人认为没有Scala的函数式那么纯粹。return是用在函数里面来返回一个值给调用者。

1
2
3
fun foo(): Int {
return 3
}

当执行到return时候,函数立即返回,仅仅只是最接近return的那个函数返回,看下面两个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
fun baz() {
(1..10).forEach(fun(value: Int) {
if (value == 2) return
println(value)
})
}
fun jaz() {
(1..10).forEach {
if (it == 2) return
println(it)
}
}

baz函数会打印1, 3, 4, 5, 6, 7, 8, 9, 10,而没有2,因为在循环到2的时候匿名函数直接返回了,但是forEach还在继续执行。
而jaz函数仅仅打印1,这里使用的是lambda来代替显示的fun定义。

来看下下面两个函数foobar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun foo() {
(1..10).map lit@ {
if (it == 2) {
return@lit
}
println(it)
}
}
fun bar(): Unit {
(1..10).map {
if (it == 2) {
return
}
println(it)
}
}

这两个函数与上面的baz, jaz是一样的,使用了标签的return,就像是使用匿名的fun定义一样,不会阻止循环的执行。

在使用forEach迭代的时候,默认有一个forEach@标签,可以直接使用return@forEach。另外使用了标签的return后面是可以带上一个值的,例如:return@abc 123