在Scala中一次捕获多个异常


Answers:


165

您可以将整个模式绑定到这样的变量:

try {
   throw new java.io.IOException("no such file")
} catch {
   // prints out "java.io.IOException: no such file"
   case e @ (_ : RuntimeException | _ : java.io.IOException) => println(e)
}

参见Scala语言规范第118页第8.1.11段,称为模式替代。

观看“模式匹配发布”,深入了解Scala中的模式匹配。


sbt clean coverage test coverageReport在撰写本文时,它不会通过... github.com/scoverage/sbt-scoverage/issues/257
Yordan Georgiev

32

由于可以在catch子句中使用scala的完整模式匹配功能,因此您可以执行以下操作:

try {
  throw new IOException("no such file")
} catch {
  case _ : SQLException | _ : IOException => println("Resource failure")
  case e => println("Other failure");
}

请注意,如果您需要一次又一次编写相同的处理程序,则可以为此创建自己的控制结构:

def onFilesAndDb(code: => Unit) { 
  try { 
    code 
  } catch {
    your handling code 
  }
}

对象scala.util.control.Exceptions中提供了一些此类方法。失败,failAsValue,处理可能正是您需要的

编辑:与下面所说的相反,可以绑定替代模式,因此所提出的解决方案不必要地复杂。请参阅@agilesteel解决方案

不幸的是,使用此解决方案,您无法使用其他模式访问异常。据我所知,您不能使用case绑定其他模式e @ (_ : SqlException | _ : IOException)。因此,如果需要访问异常,则必须嵌套匹配器:

try {
  throw new RuntimeException("be careful")
} catch  {
  case e : RuntimeException => e match {
    case _ : NullPointerException | _ : IllegalArgumentException => 
      println("Basic exception " + e)
    case a: IndexOutOfBoundsException => 
      println("Arrray access " + a)
    case _ => println("Less common exception " + e)
  }
  case _ => println("Not a runtime exception")
}

有趣的是,我之前从未见过模式替代方案。我认为它们未包含在PinS中
kassens 2011年

1
绑定模式替代方案有效,在这种情况下特别有用。绑定变量甚至会获得替代品最具体的通用超类型的类型。嵌套游行者是不必要的。如果您这样说,我会赞成您的回答。
Jean-Philippe Pellet

@ Jean-Philippe:太好了!我在回答之前尝试过,但无法完成该工作。检查规范可能太快了,我认为它也是如此(在第113页上,替代品是Pattern,您只能在Pattern3上绑定)。语法是什么?
Didier Dupont

16

您也可以使用scala.util.control.Exception

import scala.util.control.Exception._
import java.io.IOException

handling(classOf[RuntimeException], classOf[IOException]) by println apply { 
  throw new IOException("foo") 
}

这个特定的示例可能不是说明如何使用它的最佳示例,但是我发现它在许多情况下非常有用。


0

这对我来说是唯一的方法,它通过了低谷sbt clean coverage test coverageReport而又没有引发讨厌的解析异常……

try {
   throw new CustomValidationException1( 
      CustomErrorCodeEnum.STUDIP_FAIL,
      "could be throw new CustomValidationException2")
    } catch {
    case e
      if (e.isInstanceOf[CustomValidationException1] || e
      .isInstanceOf[CustomValidationException2]) => {
        // run a common handling for the both custom exceptions
        println(e.getMessage)
        println(e.errorCode.toString) // an example of common behaviour 
    }
    case e: Exception => {
      println("Unknown error occurred while reading files!!!")
      println(e.getMessage)
      // obs not errorCode available ...
    }
}

    // ... 
    class CustomValidationException1(val errorCode: CustomErrorCodeEnum, val message: String)
    class CustomValidationException2(val errorCode: CustomErrorCodeEnum, val message: String)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.