Scala Language
Fehlerbehandlung
Suche…
Versuchen
Verwenden Sie Try with map
, getOrElse
und flatMap
:
import scala.util.Try
val i = Try("123".toInt) // Success(123)
i.map(_ + 1).getOrElse(321) // 124
val j = Try("abc".toInt) // Failure(java.lang.NumberFormatException)
j.map(_ + 1).getOrElse(321) // 321
Try("123".toInt) flatMap { i =>
Try("234".toInt)
.map(_ + i)
} // Success(357)
Verwenden Try
with pattern match:
Try(parsePerson("John Doe")) match {
case Success(person) => println(person.surname)
case Failure(ex) => // Handle error ...
}
Entweder
Unterschiedliche Datentypen für Fehler / Erfolg
def getPersonFromWebService(url: String): Either[String, Person] = {
val response = webServiceClient.get(url)
response.webService.status match {
case 200 => {
val person = parsePerson(response)
if(!isValid(person)) Left("Validation failed")
else Right(person)
}
case _ => Left(s"Request failed with error code $response.status")
}
}
Musterabgleich bei jedem Wert
getPersonFromWebService("http://some-webservice.com/person") match {
case Left(errorMessage) => println(errorMessage)
case Right(person) => println(person.surname)
}
Wandeln Sie einen der beiden Werte in eine Option um
val maybePerson: Option[Person] = getPersonFromWebService("http://some-webservice.com/person").right.toOption
Möglichkeit
Von der Verwendung von null
wird dringend abgeraten, es sei denn, es wird mit älterem Java-Code interagiert, der null
erwartet. Stattdessen sollte Option
verwendet werden, wenn das Ergebnis einer Funktion entweder etwas ( Some
) oder nichts ( None
) ist.
Ein try-catch-Block ist eher für die Fehlerbehandlung geeignet, aber wenn die Funktion legitimerweise nichts Option
ist Option
angemessen und einfach zu verwenden.
Eine Option[T]
kann entweder Some(value)
(enthält einen Wert vom Typ T
) oder None
:
def findPerson(name: String): Option[Person]
Wenn keine Person gefunden wird, kann None
zurückgegeben werden. Andernfalls wird ein Objekt vom Typ Some
das ein Person
Objekt enthält. Im Folgenden werden Möglichkeiten beschrieben, mit einem Objekt vom Typ Option
.
Musterabgleich
findPerson(personName) match {
case Some(person) => println(person.surname)
case None => println(s"No person found with name $personName")
}
Map und getOrElse verwenden
val name = findPerson(personName).map(_.firstName).getOrElse("Unknown")
println(name) // Prints either the name of the found person or "Unknown"
Falte verwenden
val name = findPerson(personName).fold("Unknown")(_.firstName)
// equivalent to the map getOrElse example above.
Konvertieren nach Java
Wenn Sie einen Option
für die Interoperabilität in einen nullfähigen Java-Typ konvertieren müssen:
val s: Option[String] = Option("hello") s.orNull // "hello": String s.getOrElse(null) // "hello": String val n: Option[Int] = Option(42) n.orNull // compilation failure (Cannot prove that Null <:< Int.) n.getOrElse(null) // 42
Fehler in der Zukunft behandeln
Wenn eine exception
innerhalb einer Future
ausgelöst wird, können Sie (sollten) es verwenden, recover
damit umzugehen.
Zum Beispiel,
def runFuture: Future = Future { throw new FairlyStupidException }
val itWillBeAwesome: Future = runFuture
... wird eine Exception
aus der Future
werfen. Da wir jedoch mit einer hohen Wahrscheinlichkeit vorhersagen können, dass eine Exception
vom Typ FairlyStupidException
, können wir diesen Fall auf elegante Weise gezielt behandeln:
val itWillBeAwesomeOrIllRecover = runFuture recover {
case stupid: FairlyStupidException =>
BadRequest("Another stupid exception!")
}
Wie Sie sehen, ist die recover
Methode eine PartialFunction
über die Domäne von All Throwable
. Sie können also nur einige wenige Typen behandeln und dann den Rest in den Äther der Ausnahmebehandlung auf höheren Ebenen des Future
Stacks gehen lassen.
Beachten Sie, dass dies dem Ausführen des folgenden Codes in einem nicht- Future
Kontext ähnelt:
def runNotFuture: Unit = throw new FairlyStupidException
try {
runNotFuture
} catch {
case e: FairlyStupidException => BadRequest("Another stupid exception!")
}
Es ist sehr wichtig, Ausnahmen zu behandeln, die in Future
s generiert wurden, da sie meistens hinterlistiger sind. Sie bekommen in der Regel nicht alles ins Gesicht, weil sie in einem anderen Ausführungskontext und Thread ausgeführt werden und Sie daher nicht dazu aufgefordert werden, sie zu beheben, wenn sie auftreten, insbesondere wenn Sie nichts in den Protokollen oder das Verhalten des Befehls feststellen Anwendung.
Try-Catch-Klauseln verwenden
Neben funktionalen Konstrukten wie Try
, Option
und Either
für die Fehlerbehandlung unterstützt Scala auch eine ähnliche Syntax wie die von Java, wobei eine Try-Catch-Klausel verwendet wird (die möglicherweise auch zum Schluss blockiert). Die catch-Klausel ist eine Musterübereinstimmung:
try {
// ... might throw exception
} catch {
case ioe: IOException => ... // more specific cases first
case e: Exception => ...
// uncaught types will be thrown
} finally {
// ...
}
Konvertieren Sie Ausnahmen in entweder einen oder einen Optionstyp
Um Ausnahmen in die Typen " Either
oder " Option
zu konvertieren, können Sie Methoden verwenden, die in scala.util.control.Exception
bereitgestellt scala.util.control.Exception
import scala.util.control.Exception._
val plain = "71a"
val optionInt: Option[Int] = catching(classOf[java.lang.NumberFormatException]) opt { plain.toInt }
val eitherInt = Either[Throwable, Int] = catching(classOf[java.lang.NumberFormatException]) either { plain.toInt }