Scala版:
object Test {
def main(args: Array[String]) {
val list = List("A", "B", "C")
list.foreach(s=>{
if (s == "C") {
println("ok, do something.")
return;
}
})
println("111")
}
}
运行结果:
ok, do something.
是不是感觉很纳闷,没有打印111
。实质上scala里的lambda表达式中的return背后实际是通过特定的异常来实现的。return在嵌套的匿名函数里是无法跳出外层函数的,所以编译器通过抛出scala.runtime.NonLocalReturnControl
异常来实现跳出最外层。所有的lambda中使用return都是如此。因此稍作修改就可以了。
object Test {
def main(args: Array[String]) {
try {
val list = List("A", "B", "C")
list.foreach(s => {
if (s == "C") {
println("ok, do something.")
return
}
})
}catch {
case e: ControlThrowable => println("222")//要注意对ControlThrowable的捕获,不要干扰流控逻辑:
}
println("111")
}
}
如下示例,实质上还是会取得返回值:
object Test {
def main(args: Array[String]) {
println(test)
println("111")
}
def test: Boolean = {
val list = List("A", "B", "C")
list.foreach(s => {
if (s == "C") {
println("ok, do something.")
return true
}
})
false
}
}
运行结果:
ok, do something.
true
111
可以看看它编译的中间环节:
$ scalac -Xprint:explicitouter Test.scala
[[syntax trees at end of explicitouter]] // Test.scala
package org.zero {
object Test extends Object {
def <init>(): org.zero.Test.type = {
Test.super.<init>();
()
};
def main(args: Array[String]): Unit = {
scala.this.Predef.println(Test.this.test());
scala.this.Predef.println("111")
};
def test(): Boolean = {
<synthetic> val nonLocalReturnKey1: Object = new Object();
try {
val list: List[String] = immutable.this.List.apply[String](scala.this.Predef.wrapRefArray[String](Array[String]{"A", "B", "C"}));
list.foreach[Unit]({
@SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1[String,Unit] with Serializable {
def <init>(): <$anon: String => Unit> = {
$anonfun.super.<init>();
()
};
final def apply(s: String): Unit = if (s.==("C"))
{
scala.this.Predef.println("ok, do something.");
throw new scala.runtime.NonLocalReturnControl$mcZ$sp(nonLocalReturnKey1, true)
}
else
()
};
(new <$anon: String => Unit>(): String => Unit)
});
false
} catch {
case (ex @ (_: scala.runtime.NonLocalReturnControl[Boolean @unchecked])) => if (ex.key().eq(nonLocalReturnKey1))
ex.value$mcZ$sp()
else
throw ex
}
}
}
}
可以发现,对于return true,scala将它封装成了scala.runtime.NonLocalReturnControl$mcZ$sp(nonLocalReturnKey1, true)
,在之后的catch块中取得NonLocalReturnControl中的value值然后返回。
Java版:
public static void main(String[] args) {
List<String> list = Arrays.asList("a","b");
list.forEach(s->{
if(s.equals("b")) return;
});
System.out.println(111);
}
运行结果:
111
Java对于lamdba表达式中的return处理还是按照之前逻辑处理的。