skip to content

Exceptions & try/catch as Expression

Kotlin has no checked exceptions, try is an expression that returns a value, and throw has type Nothing. The interview conversation is usually about what Kotlin gained and lost by dropping checked exceptions, especially at the Java boundary.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

Does Kotlin have checked exceptions? Do you need to declare or catch the exceptions a function might throw?

level: juniorimportance: must knowfreq 78%

answer

  1. All Kotlin exceptions are unchecked
  2. No 'throws' keyword in signatures
  3. @Throws only for Java interop
  4. Compiler never forces try/catch
  5. Design choice: avoid boilerplate catch

basics

~10 s

No. In Kotlin every exception is unchecked. You are never forced to catch an exception or list it in the function signature. There is no 'throws' clause like in Java.

solid answer

~40 s

Kotlin has no checked exceptions. Every Throwable is treated as unchecked, so the compiler never forces you to wrap a call in try/catch or declare what it throws. There is no `throws` keyword in a function signature. This is a deliberate language decision: Roman Elizarov and the Kotlin team argued checked exceptions in large codebases lead to boilerplate `catch` blocks that swallow or rethrow. You can still catch anything you like with `try/catch`. When calling Kotlin from Java, you add the `@Throws(IOException::class)` annotation so the generated Java method declares the checked exception, satisfying Java callers. Without it, Java code that needs the declaration won't compile against your Kotlin API. The annotation changes only the generated bytecode signature; it has no effect on Kotlin callers.

go deeper

for a junior

Knows there are no checked exceptions and try/catch is optional.

for a middle

Explains the design rationale and mentions @Throws for interop.

for a senior

Articulates the bytecode-signature effect of @Throws and when Java callers break without it.

for a principal

Discusses API-design tradeoffs of unchecked-only exceptions and team conventions for documenting throwable failures.

## Checked vs unchecked exceptions In Java, exceptions are split into two groups: - **Checked exceptions** (subclasses of `Exception` but not `RuntimeException`, e.g. `IOException`): the compiler *forces* the caller to either catch them or declare them with `throws` in the method signature. - **Unchecked exceptions** (subclasses of `RuntimeException` and `Error`): no compiler enforcement. ## Kotlin's rule: everything is unchecked Kotlin treats **all** exceptions as unchecked. The compiler never requires you to: - wrap a call in `try/catch`, or - declare thrown types in the function signature (there is no `throws` keyword in Kotlin at all). This means code like reading a file compiles with no ceremony: ```kotlin fun read(path: String): String = java.io.File(path).readText() // can throw IOException, no catch required ``` ## Why this design The Kotlin team's position is that checked exceptions, in large codebases, encourage low-quality `catch` blocks that either swallow the exception or blindly rethrow it, adding boilerplate without improving reliability. So Kotlin removed the enforcement while keeping the `try/catch` machinery for when you genuinely want to handle a failure. ## Interop: `@Throws` Because Java still cares about checked exceptions, Kotlin provides the `@Throws` annotation. It does not change Kotlin semantics; it only adds a `throws` clause to the **generated Java bytecode signature** so Java callers can (and must) handle it: ```kotlin @Throws(java.io.IOException::class) fun loadConfig(path: String): String = java.io.File(path).readText() ``` Without `@Throws`, Java code calling `loadConfig` and surrounding it with `catch (IOException e)` will fail to compile, because Java thinks the method never throws a checked exception. ## Key terms - **Throwable**: the root type of everything you can `throw` or `catch`. - **Unchecked**: not enforced by the compiler. - **`@Throws`**: interop-only annotation for Java callers.

  • If exceptions are unchecked, how does a Java caller know to catch a Kotlin function's IOException?
    It doesn't, unless you annotate the Kotlin function with @Throws(IOException::class), which emits a Java 'throws' clause in the bytecode signature.
  • Does @Throws change behavior for Kotlin callers?
    No. Kotlin callers are still never forced to catch it; @Throws affects only the generated Java signature.

Java's checked exceptions are like a form you must fill in at every door; Kotlin removes the form but the doors are still there if you choose to use them.

saying these in an interview costs you the question

  • Saying Kotlin has checked exceptions like Java
  • Claiming the compiler forces you to catch IOException
  • Thinking @Throws makes Kotlin callers catch the exception
  • Believing there is a 'throws' keyword in Kotlin signatures

context

open as a page

Which runtime exception types does the Kotlin stdlib throw for common operations, and when is each raised?

level: middleimportance: must knowfreq 64%

basics

~20 s

The stdlib throws specific runtime exceptions: bad numeric text gives NumberFormatException, a null in a non-null spot gives NullPointerException, a bad index gives IndexOutOfBoundsException, an empty collection's first() gives NoSuchElementException, and a wrong cast gives ClassCastException.

open as a page

How does try/catch behave as an expression in Kotlin? What value does it produce, and how does finally interact with that value?

level: middleimportance: must knowfreq 70%

basics

~20 s

In Kotlin try/catch can return a value. The result is the last expression of whichever block runs — the try block if it succeeds, or the matching catch block if it fails. A finally block runs but does not change the returned value.

open as a page

Describe Kotlin's Throwable hierarchy. What are Throwable, Exception, RuntimeException, and Error, and which should you typically catch?

level: middleimportance: should knowfreq 58%

basics

~20 s

Throwable is the root of everything you can throw or catch. Exception and Error are its two children. Exception (and its child RuntimeException) means recoverable problems; Error means serious JVM failures you normally let crash. Catch Exception, not Throwable.

open as a page

What is the type of a 'throw' expression in Kotlin, and how does the Nothing type make throw usable in places that expect a value?

level: seniorimportance: should knowfreq 52%

basics

~20 s

A throw expression has type Nothing, the type with no values that is a subtype of every type. Because it fits anywhere, you can use throw on the right side of ?: (Elvis), as a when branch, or as a single-expression function body.

open as a page