Scala Language
Обработка ошибок
Поиск…
Пытаться
Использование Try с map
, getOrElse
и 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)
Использование Try
с сопоставлением с образцом:
Try(parsePerson("John Doe")) match {
case Success(person) => println(person.surname)
case Failure(ex) => // Handle error ...
}
Или
Различные типы данных для ошибки / успеха
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")
}
}
Совпадение шаблонов по любому значению
getPersonFromWebService("http://some-webservice.com/person") match {
case Left(errorMessage) => println(errorMessage)
case Right(person) => println(person.surname)
}
Преобразовать любое значение в параметр
val maybePerson: Option[Person] = getPersonFromWebService("http://some-webservice.com/person").right.toOption
вариант
Использование null
значений категорически не рекомендуется, если они не взаимодействуют с устаревшим кодом Java, который ожидает null
. Вместо этого, Option
следует использовать , когда результат функции может быть что - то ( Some
) или ничего ( None
).
Блок try-catch более подходит для обработки ошибок, но если функция может законно вернуть ничего, Option
подходит для использования и проста.
Option[T]
может быть либо Some(value)
(содержит значение типа T
), либо None
:
def findPerson(name: String): Option[Person]
Если ни один человек не найден, None
может быть возвращено. В противном случае возвращается объект типа Some
содержащий объект Person
. Ниже приведены способы обработки объекта типа Option
.
Соответствие шаблону
findPerson(personName) match {
case Some(person) => println(person.surname)
case None => println(s"No person found with name $personName")
}
Использование карты и getOrElse
val name = findPerson(personName).map(_.firstName).getOrElse("Unknown")
println(name) // Prints either the name of the found person or "Unknown"
Использование сгиба
val name = findPerson(personName).fold("Unknown")(_.firstName)
// equivalent to the map getOrElse example above.
Преобразование в Java
Если вам требуется преобразовать тип Option
в нулевой Java-тип для взаимодействия:
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
Обработка ошибок, возникающих в фьючерсах
Когда exception
выбрасывается из Future
, вы можете (должны) использовать recover
для его обработки.
Например,
def runFuture: Future = Future { throw new FairlyStupidException }
val itWillBeAwesome: Future = runFuture
... выкинет Exception
из Future
. Но, видя, что мы можем с высокой вероятностью предсказать, что Exception
типа FairlyStupidException
с большой вероятностью, мы можем специально обработать этот случай элегантным способом:
val itWillBeAwesomeOrIllRecover = runFuture recover {
case stupid: FairlyStupidException =>
BadRequest("Another stupid exception!")
}
Как вы видите, метод, данный для recover
является PartialFunction
над доменом всех Throwable
, поэтому вы можете обрабатывать только несколько типов, а затем позволить остальным перейти в эфир обработки исключений на более высоких уровнях в стеке Future
.
Обратите внимание, что это похоже на запуск следующего кода в контексте, не относящемся к Future
:
def runNotFuture: Unit = throw new FairlyStupidException
try {
runNotFuture
} catch {
case e: FairlyStupidException => BadRequest("Another stupid exception!")
}
Очень важно обрабатывать исключения, созданные в Future
потому что большую часть времени они более коварны. Обычно они не получают все на вашем лице, потому что они работают в другом контексте исполнения и потоке и, следовательно, не предлагают вам исправить их, когда они происходят, особенно если вы ничего не замечаете в журналах или поведение приложение.
Использование предложений try-catch
В дополнение к функциональным конструкциям, таким как Try
, Option
и Either
для обработки ошибок, Scala также поддерживает синтаксис, подобный Java, с использованием предложения try-catch (с потенциальным, наконец, блоком). Предложение catch - это совпадение с шаблоном:
try {
// ... might throw exception
} catch {
case ioe: IOException => ... // more specific cases first
case e: Exception => ...
// uncaught types will be thrown
} finally {
// ...
}
Преобразование исключений в типы или типы
Для преобразования исключения в Either
или Option
тип, вы можете использовать методы, предусмотренные в 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 }