一、lambda中的返回语句:从一个封闭的函数返回
- 在一个普通循环中使用
return
fun lookForAlice(people: List<PersonNew>) {
for(person in people) {
if(person.name == "Alice") {
println("Found")
return
}
}
// 如果“people”中没有Alice,这一行就会被打印出来
println("Alice is not found")
}
fun lookForAliceTest() {
lookForAlice(people)
}
// 输出结果
Found!
- 在传递给forEach的
lambda
中使用return
fun lookForAliceByForEach(people: List<PersonNew>){
people.forEach {
if(it.name == "Alice") {
println("Found!")
return
}
}
println("Alice is not found")
}
fun lookForAliceByForEachTest() {
lookForAliceByForEach(people)
}
非局部返回:在lambda
中使用return
关键字,它会从调用lambda的函数中返回,并不只是从lambda中返回。
注意:非局部返回,是从一个比包含return的代码块中更大的代码块中返回了。
注意:只有在以
lambda
作为参数的函数是内联函数的时候才能从更外层的函数返回。
在一个非内联函数的lambda
中使用return表达式是不允许的。一个非内联函数可以把传给它的lambda保存在变量中,以便在函数返回以后可以继续使用,这个时候lambda想要去影响函数的返回已经太晚了。
二、从lambda返回:使用标签返回
可以在lambda
表达式中使用局部返回。lambda中的局部返回跟for
循环中的break
表达式相似。它会终止lambda的执行,并接着从调用lambda的代码处执行。
要区分局部返回和非局部返回,要用到标签。想从一个lambda表达式处返回你可以标记它,然后在return关键字后面引用这个标签。
- 用一个标签实现局部返回
fun lookForAliceByLabel(people: List<PersonNew>){
people.forEach label@ {
// return@label引用了
if(it.name == "Alice") return@label
}
// 这一行总是会被打印出来
println("Alice might be somewhere")
}
fun lookForAliceByLabelTest() {
lookForAliceByLabel(people)
}
// 输出结果
Alice might be somewhere
-
要标记一个
lambda
表达式,在lambda
的花括号之前放一个标记名(可以是任何标识符),接着放要给**@
字符**。 -
要从一个**
lambda
返回**,在**return
关键字后放一个@
符号**,接着放标签名,如图1:
- 用函数名作为return标签
fun lookForAliceByLabel1(people: List<PersonNew>) {
people.forEach {
// return@forEach 从lambda表达式返回
if(it.name == "Alice") return@forEach
}
println("Alice might be somewhere")
}
显式地指定了**lambda
表达式的标签**,再使用函数名作为标签没有任何效果。一个lambda表达式的标签数量不能多于一个。
- 带标签的“this”表达式
fun lambdaTest() {
// 这个lambda的隐式接受者可以通过this@sb访问
println(StringBuilder().apply sb@ {
// “this” 指向作用域内最近的隐式接受者
listOf(1, 2, 3).apply {
// 所有隐式接受者都可以被访问,外层的接受者通过显式的标签访问
this@sb.append(this.toString())
}
})
}
同样的规则也适用于**this
表达式的标签**,带接受者的lambda
——包含一个隐式上下文对象的lambda可以通过一个this引用去访问。
和return表达式中使用标签一样,可以显示地指定lambda表达式的标签,也可以使用函数名作为标签。
三、匿名函数:默认使用局部返回
匿名返回是一种不同的用于编写传递给函数的代码块的方式。
- 在匿名函数汇总使用return
fun lookForAliceByAnonymousFunction(people: List<PersonNew>) {
people.forEach(fun (person) {
// 使用匿名函数取代lambda表达式
if(person.name == "Alice") return
// “return”指向最近的函数:一个匿名函数
println("${person.name} is not Alice")
})
}
fun lookForAliceByAnonymousFunctionTest() {
lookForAliceByAnonymousFunction(people)
}
// 输出结果
Bob is not Alice
匿名函数看起来跟普通函数很相似,除了它的名字和参数类型被省略了外。
在匿名函数中,不带标签的return
表达式会从匿名函数返回,而不是从包含匿名函数的函数返回。
这条规则很简单:
return
从最近的使用fun
关键字声明的函数返回。lambda
表达式没有使用**fun
关键字**,所以lambda中的return
从最外层的函数返回。