ProgrammingBackend Developer (Kotlin)

How does exception handling work in Kotlin? What is the difference between Kotlin's approach and Java's, how to handle exceptions, what are the nuances with checked/unchecked exceptions, and how does the use of try/catch/finally influence this?

Pass interviews with Hintsage AI assistant

Answer.

In Kotlin, exception handling is implemented through the try/catch/finally construct, but differs from Java's approach by emphasizing unchecked exceptions and a more concise syntax. A significant distinction is that Kotlin does not have checked exceptions, relieving the programmer from the obligation to specify throws and catch such exceptions.

Background

Java uses checked/unchecked exceptions, where checked exceptions require explicit catching or declaration. This often leads to excessive boilerplate and cumbersome code. Kotlin is designed to be simpler — all exceptions are typically unchecked (inherited from RuntimeException), making it easier to handle and rendering the code more readable.

The Problem

Java developers try to catch and specify checked exceptions in Kotlin — the code compiles, but the meaning is lost. Furthermore, using finally without being aware of the nuances can lead to leaks or non-functional code.

The Solution

We use try/catch/finally in Kotlin concisely and effectively:

fun process(data: String): Int = try { data.toInt() } catch (e: NumberFormatException) { 0 } finally { println("Processing done") }
  • try/catch/finally can be an expression, meaning it can return a value that becomes the final output of the function or is assigned to a variable.
  • You can catch multiple exceptions and use when-switch within catch for different reactions to exception types.

Key Features:

  • No checked exceptions — no need to declare or explicitly handle them.
  • The try construct can work as an expression (returns a result).
  • Finally can be used for cleanup actions (e.g., closing resources), but you should not perform operations that modify the return value.

Trick Questions.

What happens if an exception is thrown in the finally block? How does this affect the return value?

Exceptions thrown from finally always override any other exceptions or return from the try/catch block, which can lead to loss of important information about the cause of the failure.

fun demo(): Int = try { 1 } finally { throw RuntimeException("error in finally") }

Can try/catch be an expression in Kotlin? What is the difference from Java?

Yes. try/catch/finally in Kotlin are expressions, so they can return a result and be used in places where values are allowed.

val value = try { risky() } catch (e: Exception) { fallback() }

In Java, these are only statements.

Is it necessary to catch exceptions in Kotlin if a third-party Java function with throws is called?

No. Since checked exceptions are ignored by the Kotlin compiler: you do not need to catch them explicitly, but they can still be thrown at runtime.

Common Mistakes and Anti-Patterns

  • Unnecessary catching of all exceptions (catch (e: Exception)) — catching what cannot be handled correctly.
  • Incorrect use of finally — modifying return values or re-throwing exceptions.
  • Attempts to use throws declarations within Kotlin code.

Real-Life Example

Negative Case

Catching (e: Exception) everywhere without differentiating between real and expected errors. Using finally to return a value, leading to unexpected behavior when errors occur.

Pros:

  • Quite resilient code against any failures.

Cons:

  • Difficult to debug.
  • Error messages and the reasons for their occurrence are lost.
  • Real problems are hidden.

Positive Case

Catching only expected errors, using finally only for resource cleanup, and using try/catch as expressions where it enhances readability.

Pros:

  • Easy to read, maintain, and test.
  • Transparent error handling.

Cons:

  • Requires discipline in API design and exception handling.