斯卡拉捉迷藏

时间:2011-04-20 18:58:59

标签: exception scala

我最近看过这样的代码:

val maybeInt = catching(classOf[NFE]) opt arg.toInt

这是opt是什么?一个选项?为什么不使用getOrElse来提取值?在上面的代码中,如果抛出NumberFormatException,maybeInt是否为None?

2 个答案:

答案 0 :(得分:35)

catching看起来像某种方法调用,不是吗?它是,但它实际上返回一个类Catch的实例;它没有直接参与论证。这个类有两个方法,对于处理异常特别有用(还有几个用于捕获多个异常)。第一个是

def opt [U >: T] (body: ⇒ U) : Option[U]
在这里使用的

- 你给它一些可能引发异常的东西,如果一切正常,它将返回Some(result),如果抓住了目标异常,它将返回None

scala> type NFE = NumberFormatException
defined type alias NFE

scala> import scala.util.control.Exception._
import scala.util.control.Exception._

scala> catching(classOf[NFE]).opt( "fish".toInt )
res0: Option[Int] = None

scala> catching(classOf[NFE]).opt( "42".toInt )  
res1: Option[Int] = Some(42)

然后,您可以使用mapfiltergetOrElse或您用来处理选项的任何其他内容来解决此问题。

另一个有用的方法是either,如果抛出异常则返回Left(exception)的实例,如果不是则返回Right(result)

scala> catching(classOf[NFE]).either( "fish".toInt )
res2: Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "fish")

scala> catching(classOf[NFE]).either( "42".toInt )
res3: Either[Throwable,Int] = Right(42)

然后,您可以使用fold或映射到选项或您喜欢的任何其他内容。

请注意,您可以定义单个捕获器并多次使用它(因此您不必每次都创建捕获器对象,例如,解析整数):

scala> val catcher = catching(classOf[NFE])
catcher: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException)

scala> catcher.opt("42".toInt)
res4: Option[Int] = Some(42)

scala> catcher.opt("fish".toInt)
res5: Option[Int] = None

编辑:丹尼尔在评论中指出,这仍然会创建一个临时的Catch[Option];给定方法签名,没有一种简单的方法可以让它捕获异常并生成选项而无需创建任何额外的对象。这让我想起为什么我会编写自己的方法来做到这一点:

def optNFE[T](t: => T) = try { Some(t) } catch {case nfe: NFE => None}
optNFE( "fish".toInt )  // gives None
optNFE( "42".toInt ) // gives Some(42)

答案 1 :(得分:0)

当只有一个捕获时,我使用更简单的模式:

 try{
      return args.split(" ").exists(line.startsWith _)
 }catch {
    case _ =>{//generic exception
      logger.error("Error with line ${line} for ${ex.message}")
      throw _
    }    
 }

我绝对不是Scala专业人士,我想你可以找到更短的东西