在java中跳出循环的时候,我们可以直接break就行了,但是在scala里面没有break,那怎么跳出循环呢?
直接看下面的demo:
package test import scala.util.control.Breaks object ListDemo { def main(args: Array[String]): Unit = { var loop = Breaks var i = 0 loop.breakable { while (i < 10) { println(i) i += 1 if (i == 5) { loop.break() } } } } }
这个地方需要用loop.breakable包括一下,不然会报一个错
Exception in thread "main" scala.util.control.BreakControl
下面看一下Breaks的源码:
/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ package scala package util.control /** A class that can be instantiated for the break control abstraction. * Example usage: * {{{ * val mybreaks = new Breaks * import mybreaks.{break, breakable} * * breakable { * for (...) { * if (...) break() * } * } * }}} * Calls to break from one instantiation of `Breaks` will never * target breakable objects of some other instantiation. */ class Breaks { private val breakException = new BreakControl /** * A block from which one can exit with a `break`. The `break` may be * executed further down in the call stack provided that it is called on the * exact same instance of `Breaks`. */ def breakable(op: => Unit) { try { op } catch { case ex: BreakControl => if (ex ne breakException) throw ex } } sealed trait TryBlock[T] { def catchBreak(onBreak: =>T): T } /** * This variant enables the execution of a code block in case of a `break()`: * {{{ * tryBreakable { * for (...) { * if (...) break() * } * } catchBreak { * doCleanup() * } * }}} */ def tryBreakable[T](op: =>T) = new TryBlock[T] { def catchBreak(onBreak: =>T) = try { op } catch { case ex: BreakControl => if (ex ne breakException) throw ex onBreak } } /** * Break from dynamically closest enclosing breakable block using this exact * `Breaks` instance. * * @note This might be different than the statically closest enclosing block! */ def break(): Nothing = { throw breakException } } /** An object that can be used for the break control abstraction. * Example usage: * {{{ * import Breaks.{break, breakable} * * breakable { * for (...) { * if (...) break * } * } * }}} */ object Breaks extends Breaks private class BreakControl extends ControlThrowable
从上面的源码可以看出,breakable与break方法组合用于控制循环的原理就是利用break方法抛出一个异常,然后breakable方法再捕获这个异常,从而结束整个breakable方法块内代码的执行,但是不影响breakable方法体外代码的执行,从而实现控制。