lambda表达式中的return

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处理还是按照之前逻辑处理的。

参考:http://hongjiang.info/scala-pitfalls-27/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值