Can a `try`/`catch` block be used as an expression in Kotlin? How is its value determined?
answer
- try is an expression; value = last expr of try or matching catch
- finally runs but never sets the value
- result type = common supertype of try + catch values
- runCatching {} -> Result<T> for functional style
- always catch the specific exception type
basics
~20 sYes. A try/catch can return a value. If the try block succeeds, its last expression is the result; if it throws and a catch handles it, that catch block's last expression is the result. A finally block never affects the value.
solid answer
~40 sYes — `try` is an expression in Kotlin. Its value is the **last expression of the `try` block** if no exception is thrown, otherwise the **last expression of the matching `catch` block**. A `finally` block runs for cleanup but **never contributes** to the resulting value. This lets you write `val x = try { parse(s) } catch (e: NumberFormatException) { 0 }`. The result type is the common supertype of the `try` and all `catch` branch values. As with other expression constructs, branch values come from the last expression. If a `catch` rethrows or the only path throws, the type can be `Nothing`. Idiomatically, prefer `runCatching { ... }` returning a `Result<T>` for functional-style handling; the `try` expression is best for a small, local recover-with-default.
code
kotlin · 10 linesval value = try {
risky() // result if it succeeds
} catch (e: IOException) {
fallback() // result if IOException is thrown
} finally {
cleanup() // runs, but does NOT influence `value`
}
// Functional alternative:
val r: Int = runCatching { risky() }.getOrElse { 0 }go deeper
May only know try/catch as control flow, not that it yields a value.
Knows try is an expression and that try/catch last expressions provide the value.
Explains finally never affects the value, the common-supertype result type, and when to prefer runCatching/Result.
Weighs exception-based vs Result-based error modeling across an API, and the readability/composition tradeoffs at scale.
## `try` is an expression In Kotlin `try`/`catch`/`finally` can produce a value: ```kotlin val port: Int = try { env("PORT").toInt() // value if no exception } catch (e: NumberFormatException) { 8080 // value if this catch matches } ``` ## How the value is determined - **No exception:** the value is the **last expression** of the `try` block. - **Exception caught:** the value is the **last expression** of the **matching `catch`** block. - **`finally`:** always executes for cleanup but **does not** affect the resulting value — even if it contains expressions, they're ignored for the result. ```kotlin val r = try { 1 } finally { 2 } // r == 1, the finally's 2 is ignored ``` ## Result type The type is the **common supertype** of the try block value and every catch block value. If a branch always throws, its contribution is `Nothing`, which doesn't widen the type. ## When to use it vs `runCatching` The `try` expression is great for a localized "recover with a default": ```kotlin val n = try { s.toInt() } catch (e: NumberFormatException) { -1 } ``` For a more functional flow, `runCatching { block() }` returns a `Result<T>` you can transform with `getOrElse`, `map`, `recover`, etc. Choose `runCatching` when you want to compose results; choose the `try` expression for a quick inline fallback. ## Caveats - Don't swallow exceptions silently; catch the **specific** type. - `finally` for cleanup (closing resources) — but prefer `use {}` on `Closeable`. ## Key APIs/keywords `try`/`catch`/`finally`, `runCatching`, `Result<T>`, `getOrElse`, `Nothing`, `use`.
- What is the result of `val x = try { 10 } finally { 20 }`?x is 10. The finally block executes but never contributes to the value of a try expression.
- When would you choose `runCatching` over a try expression?When you want to compose the outcome as a Result<T> — mapping, recovering, or chaining — rather than producing a single inline fallback value.
saying these in an interview costs you the question
- Believing a finally block's value can become the try expression's result
- Catching `Throwable`/`Exception` broadly just to use try as an expression
- Not knowing the value comes from the last expression of try or catch
- Confusing runCatching (returns Result) with the try expression
- Assuming try is statement-only like in Java