liveBook · Manning

Try-catch statement

As explained in Kotlin in Action, 2E

A try-catch is a Kotlin exception-handling construct that executes a protected block and handles matching exceptions in catch clauses.

Kotlin’s try-catch construct protects code that may fail, handles selected exceptions, and can run cleanup in finally. Unlike Java, Kotlin does not require a throws clause or distinguish checked from unchecked exceptions, so you choose which failures to handle. section 2.5.1

Recovering from invalid input

fun readNumber(reader: BufferedReader): Int? { try { val line = reader.readLine() return Integer.parseInt(line) } catch (e: NumberFormatException) { return null } finally { reader.close() } } The protected block reads and parses a line, catch converts invalid input into null, and finally closes the reader regardless of success or failure. section 2.5.1

try is also an expression. The last expression in the try block supplies the result when execution succeeds; the last expression in a matching catch block supplies the fallback result. A catch block may instead return from the enclosing function. section 2.5.2

Assigning a fallback value

val number = try { Integer.parseInt(reader.readLine()) } catch (e: NumberFormatException) { null } println(number) // null This form avoids an intermediate variable while making the failure value explicit. section 2.5.2

Place the handler where the exception is produced:

  • Inside launch, try-catch can handle an exception thrown by that coroutine; surrounding launch does not catch exceptions crossing the coroutine boundary. section 18.1
  • For async, await rethrows the deferred exception, so surround await with try-catch when the caller must handle the failure. section 18.1
  • For Flow, the catch operator handles upstream failures; wrap collect or place handling downstream when the failure occurs there. section 18.4.1
Listing 2.28 Using try the same way you would in Java
import java.io.BufferedReader
import java.io.StringReader
 
fun readNumber(reader: BufferedReader): Int? {    #1
    try {
        val line = reader.readLine()
        return Integer.parseInt(line)
    } catch (e: NumberFormatException) {          #2
        return null
    } finally {                                   #3
        reader.close()
    }
}
 
fun main() {
    val reader = BufferedReader(StringReader("239"))
    println(readNumber(reader))
    // 239
}

Inspect the complete reader example, including parsing, typed catching, nullable recovery, and resource cleanup. section 2.5.1

Listing 18.1 An async coroutine that throws an exception
import kotlinx.coroutines.*

fun main(): Unit = runBlocking {
   val myDeferredInt: Deferred<Int> = async {
       throw UnsupportedOperationException("Ouch!")
   }
   try {
       val i: Int = myDeferredInt.await()
       println(i)
   } catch (u: UnsupportedOperationException) {
       println("Handled: $u")
   }
}

Compare exception handling around await with handling placed inside a coroutine body. section 18.1

How Kotlin in Action, 2E covers it

How deep it goes
Explains syntax, result-value rules, cleanup, Java differences, coroutine boundaries, and Flow placement, but defers broader uncaught-exception policies.
Examples
Uses BufferedReader parsing, nullable fallback assignment, launch and async failures, and Flow default-value emission.
What it assumes
Assumes basic Kotlin functions and expressions while teaching exception recovery and Kotlin’s distinction from Java checked-exception rules.
What you can do after
Apply it via Kotlin syntax to recover from selected exceptions, return fallback values, clean up resources, and handle coroutine failures at the correct boundary.
How it connects
Connects exception handling with finally, checked exceptions, coroutines, async, await, and the Flow catch operator.

Also explained in

Compare how 10 books explain try-catch statement →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.