Введение в результат вызова в Kotlin
Результат вызова - тип Result, который хранит
либо готовое значение, либо описание сбоя. Ошибку можно
не бросать дальше по стеку: блок завершается, а снаружи
остается объект, с которым работают как с обычными данными.
Привычные try и catch по-прежнему ловят
исключение в месте риска. Класс Result добавляет другой
стиль: сбой становится частью результата выражения, и
следующие команды выполняются, пока код сам не решит,
что делать с неудачей.
Стандартная обертка runCatching принимает лямбду,
выполняет ее и возвращает Result. Если внутри
вылетело исключение, оно не идет наружу - вызов отдает
неудачный результат. Если лямбда дошла до конца, наружу
уходит успех с последним значением блока.
Разбор числа из строки часто падает на неверном символе. Обернем рискованный шаг и посмотрим, что получится для корректного и для испорченного ввода:
fun main() {
val ok = runCatching { "24".toInt() }
println(ok)
val bad = runCatching { "24x".toInt() }
println(bad)
}
Для удачной строки в консоли виден успех с числом. Для
второй строки - неудача с типом исключения и сообщением.
Программа не оборвалась на toInt: оба вызова
завершились, каждый вернул свой Result.
Тот же прием удобен, когда подряд обрабатывают несколько строк из списка. Сбой на одной позиции не мешает перейти к следующей и в конце выполнить общий шаг:
fun main() {
val inputs = listOf("10", "zero", "3")
for (raw in inputs) {
val parsed = runCatching { raw.toInt() }
println("$raw -> $parsed")
}
println("batch finished")
}
Строка "zero" дает неудачный Result, но цикл
идет дальше. Строка "batch finished" печатается
всегда - поток управления не ушел в catch на
уровне main.
Объект Result можно сохранить в переменную и
передать в другую функцию, как любое значение. Тип
напоминает: внутри либо успех, либо ошибка, и с этим
исходом работают отдельно от обычного потока
исключений.