Scala Language
Felhantering
Sök…
Prova
Använd Try med map
, getOrElse
och 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)
Använda Try
med mönstermatchning:
Try(parsePerson("John Doe")) match {
case Success(person) => println(person.surname)
case Failure(ex) => // Handle error ...
}
Antingen
Olika datatyper för fel / framgång
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")
}
}
Mönstermatchning på antingen värde
getPersonFromWebService("http://some-webservice.com/person") match {
case Left(errorMessage) => println(errorMessage)
case Right(person) => println(person.surname)
}
Konvertera antingen värde till alternativ
val maybePerson: Option[Person] = getPersonFromWebService("http://some-webservice.com/person").right.toOption
Alternativ
Användningen av null
avskräcks starkt, såvida inte interagerar med den äldre Java-koden som förväntar sig null
. I stället bör Option
användas när resultatet av en funktion antingen kan vara något ( Some
) eller ingenting ( None
).
Ett try-catch-block är mer lämpligt för felhantering, men om funktionen på ett legitimt sätt kan returnera ingenting är Option
lämpligt att använda och enkelt.
Ett Option[T]
kan antingen vara Some(value)
(innehåller ett värde av typ T
) eller None
:
def findPerson(name: String): Option[Person]
Om ingen person hittas kan None
returneras. Annars returneras ett objekt av typen Some
innehåller ett Person
objekt. Följande är sätt att hantera ett objekt av typen Option
.
Mönstermatchning
findPerson(personName) match {
case Some(person) => println(person.surname)
case None => println(s"No person found with name $personName")
}
Med hjälp av karta och getOrElse
val name = findPerson(personName).map(_.firstName).getOrElse("Unknown")
println(name) // Prints either the name of the found person or "Unknown"
Använd veck
val name = findPerson(personName).fold("Unknown")(_.firstName)
// equivalent to the map getOrElse example above.
Konvertera till Java
Om du behöver konvertera en Option
till en null-kapabel Java-typ för interoperabilitet:
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
Hantera fel med ursprung i framtiden
När ett exception
kastas från en Future
kan du (bör) använda recover
att hantera det.
Till exempel,
def runFuture: Future = Future { throw new FairlyStupidException }
val itWillBeAwesome: Future = runFuture
... kommer att kasta ett Exception
från Future
. Men eftersom vi kan förutsäga att ett Exception
av typen FairlyStupidException
med stor sannolikhet, kan vi specifikt hantera detta fall på ett elegant sätt:
val itWillBeAwesomeOrIllRecover = runFuture recover {
case stupid: FairlyStupidException =>
BadRequest("Another stupid exception!")
}
Som du kan se är metoden som givits för att recover
en PartialFunction
över domänen för alla Throwable
, så att du kan hantera bara några få typer och sedan låta resten gå in i etern för undantagshantering på högre nivåer i Future
stacken.
Observera att detta liknar köra följande kod i ett icke- Future
sammanhang:
def runNotFuture: Unit = throw new FairlyStupidException
try {
runNotFuture
} catch {
case e: FairlyStupidException => BadRequest("Another stupid exception!")
}
Det är verkligen viktigt att hantera undantag som genereras inom Future
för mycket av tiden är de mer lumska. De får inte alla i ditt ansikte vanligtvis eftersom de körs i ett annat utförande-sammanhang och tråd, och därför uppmanar dig inte att fixa dem när de händer, särskilt om du inte märker något i loggar eller beteendet hos Ansökan.
Använda try-catch klausuler
Förutom funktionella konstruktioner som Try
, Option
och Either
för felhantering stöder Scala också en syntax som liknar Java, med hjälp av en try-catch-klausul (med en potentiell slutlig block också). Fångstklausulen är en mönstermatchning:
try {
// ... might throw exception
} catch {
case ioe: IOException => ... // more specific cases first
case e: Exception => ...
// uncaught types will be thrown
} finally {
// ...
}
Konvertera undantag till antingen eller alternativstyper
Om du vill konvertera undantag till Either
eller Option
kan du använda metoder som finns i 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 }