In Scala mehrere Ausnahmen gleichzeitig abfangen


Antworten:


165

Sie können das gesamte Muster wie folgt an eine Variable binden:

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)
}

Siehe die Scala-Sprachspezifikation auf Seite 118, Abschnitt 8.1.11, die als Musteralternativen bezeichnet wird.

Sehen Sie sich Pattern Matching Unleashed an, um einen tieferen Einblick in Pattern Matching in Scala zu erhalten.


was sbt clean coverage test coverageReportzum Zeitpunkt des Schreibens nicht durchgeht
Yordan Georgiev

32

Da Sie in der catch-Klausel Zugriff auf die vollständigen Mustervergleichsfunktionen von scala haben, können Sie viel tun:

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

Beachten Sie, dass Sie, wenn Sie immer wieder dieselben Handler schreiben müssen, eine eigene Steuerungsstruktur dafür erstellen können:

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

Einige dieser Methoden sind im Objekt scala.util.control.Exceptions verfügbar . Failing, FailAsValue, Handling kann genau das sein, was Sie brauchen

Bearbeiten: Im Gegensatz zu den folgenden Ausführungen können alternative Muster gebunden werden, sodass die vorgeschlagene Lösung unnötig komplex ist. Siehe @ agilesteel-Lösung

Leider haben Sie mit dieser Lösung keinen Zugriff auf die Ausnahme, in der Sie die alternativen Muster verwenden. Meines Wissens können Sie kein alternatives Muster mit case binden e @ (_ : SqlException | _ : IOException). Wenn Sie also Zugriff auf die Ausnahme benötigen, müssen Sie Matcher verschachteln:

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")
}

Interessanterweise habe ich noch nie Musteralternativen gesehen. Ich denke, sie sind nicht in PinS abgedeckt .
Kassens

1
Das Binden einer Musteralternative funktioniert und ist in diesem Fall besonders nützlich. Die gebundene Variable erhält sogar als Typ die spezifischsten allgemeinen Supertypen der Alternativen. Das Marschieren von Marschierenden ist nicht erforderlich. Ich werde Ihre Antwort positiv bewerten, wenn Sie sie so aktualisieren.
Jean-Philippe Pellet

@ Jean-Philippe: Ausgezeichnet !! Ich habe es versucht, bevor ich geantwortet habe, und konnte das nicht zum Laufen bringen. Als ich die Spezifikation wahrscheinlich zu schnell überprüfte, dachte ich, dass sie dasselbe sagte (auf Seite 113 ist Alternative Pattern und Sie können nur Pattern3 binden). Wie ist die Syntax?
Didier Dupont

16

Sie können auch verwenden 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") 
}

Dieses spezielle Beispiel ist möglicherweise nicht das beste Beispiel, um zu veranschaulichen, wie Sie es verwenden können, aber ich finde es in vielen Fällen ziemlich nützlich.


0

Dies war der einzige Weg für mich, der durch die ging, sbt clean coverage test coverageReportohne die böse Parsing-Ausnahme zu werfen ...

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.