51. Result & runCatching
Instead of propagating an exception, runCatching { } runs a block and captures the outcome in a Result<T> — either a success holding a value or a failure holding the thrown exception. You then inspect or transform it without a try/catch.
fun parse(text: String): Int = text.toInt() // throws on bad input
fun main() {
// runCatching wraps success or failure into a Result<T>.
val ok: Result<Int> = runCatching { parse("21") }
val bad: Result<Int> = runCatching { parse("nope") }
// map transforms a success; getOrElse supplies a fallback.
println(ok.map { it * 2 }.getOrElse { -1 }) // 42
println(bad.map { it * 2 }.getOrElse { -1 }) // -1
// getOrNull returns null on failure.
println(ok.getOrNull()) // 21
println(bad.getOrNull()) // null
// onSuccess / onFailure run side-effects and return the Result.
bad
.onSuccess { println("got $it") }
.onFailure { println("failed: ${it.message}") }
}
map applies only on success and leaves a failure untouched, while getOrElse, getOrNull, and getOrThrow extract the value. onSuccess and onFailure return the same Result, so they chain naturally for logging or recovery.
Running it:
$ kotlin run
42
-1
21
null
failed: For input string: "nope"
| ← Prev | Index | Next → |