Kotlin has no checked exceptions. What does the @Throws annotation do, and why would you put it on a Kotlin function?
answer
- Kotlin = all exceptions unchecked
- @Throws emits Java 'throws' clause in bytecode
- Interop-only: no effect on Kotlin callers
- Fixes Java 'exception never thrown' error
- vararg of KClass: @Throws(IOException::class)
basics
~20 sKotlin never forces you to declare or catch exceptions. @Throws tells the compiler to add a Java 'throws' clause to the generated method, so Java code calling that Kotlin function can catch or declare the exception normally.
solid answer
~40 sIn Kotlin every exception is unchecked, so the bytecode of a Kotlin function carries no `throws` clause by default. That is fine for Kotlin-to-Kotlin calls, but Java has checked exceptions: a Java caller cannot `catch (IOException e)` unless the called method declares it, and tools/compilers complain. Annotating the Kotlin function with `@Throws(IOException::class)` makes the Kotlin compiler emit `throws IOException` in the generated JVM method signature. Now Java callers can `catch` it without an 'exception never thrown' error, or declare it on their own method. It is purely an interop hint: it changes the bytecode signature for Java's benefit and has no effect on Kotlin callers, who still are not required to handle anything.
code
kotlin · 9 linesimport java.io.IOException
@Throws(IOException::class)
fun readConfig(path: String): String =
java.io.File(path).readText()
// Java side (now legal):
// try { Configs.readConfig("a.txt"); }
// catch (IOException e) { /* handle */ }go deeper
Knows Kotlin has no checked exceptions and that @Throws adds a Java throws clause for interop.
Can explain the Java 'exception never thrown' compile error it prevents and that it is signature-only.
Frames it as a public-API interop decision and notes it accepts a vararg of KClass with no runtime effect.
Discusses API-design policy: when to expose checked-style contracts to Java consumers vs. keeping a pure-Kotlin surface.
## Background: checked vs unchecked exceptions In **Java**, exceptions are split into two groups. **Checked** exceptions (subtypes of `Exception` that are not `RuntimeException`, e.g. `IOException`) must be either caught with `try/catch` or declared with a `throws` clause on the method — the Java compiler enforces this. **Unchecked** exceptions (`RuntimeException` and `Error` subtypes) need no declaration. **Kotlin has no checked exceptions at all.** Every exception is treated like an unchecked one: you are never *required* to catch or declare anything. This is a deliberate language decision. ## The interop problem When Kotlin compiles a function, the generated JVM method has **no `throws` clause** by default. For Kotlin callers this is invisible and harmless. But a **Java** caller sees a method that declares it throws nothing. If the Java code writes: ```java try { kotlinReadFile(); } catch (IOException e) { ... } // compile error in Java ``` the Java compiler rejects it with *"exception IOException is never thrown in the corresponding try block"*, because the method signature does not declare `IOException`. ## What `@Throws` does `@Throws(vararg exceptionClasses: KClass<out Throwable>)` instructs the Kotlin compiler to write those exception types into the **`throws` clause of the generated JVM method**. It does **not** change runtime behavior, does not wrap anything, and does not affect Kotlin callers — it only edits the method's bytecode signature so Java sees a normal checked-exception declaration. ```kotlin import java.io.IOException @Throws(IOException::class) fun readConfig(path: String): String { // may throw IOException at runtime return java.io.File(path).readText() } ``` The generated method becomes the Java-visible `String readConfig(String) throws IOException`. ## Key facts - It accepts a **vararg** of `KClass` references, so you can list several: `@Throws(IOException::class, TimeoutException::class)`. - It is **interop-only**: Kotlin callers gain nothing and are still not forced to handle the exception. - It does not make Kotlin enforce anything — the function can throw the listed types or not; the annotation is purely a signature hint. - The fully qualified name is `kotlin.Throws` (in package `kotlin`, auto-imported). ## When to use it Use it on Kotlin functions that are part of a **public API consumed from Java** and that legitimately throw a checked exception Java callers should handle — e.g. I/O, parsing, or `Closeable.close()`. If your code is Kotlin-only, you almost never need it.
- Does @Throws change anything for a Kotlin caller of the function?No. Kotlin callers are never forced to catch or declare; the annotation only adds the throws clause to the JVM signature for Java's benefit.
- Can you list more than one exception?Yes — it is a vararg: @Throws(IOException::class, TimeoutException::class).
@Throws is a translator's note added to a contract so a Java reader (who insists every risk be written down) accepts it; the Kotlin reader ignores the note entirely.
saying these in an interview costs you the question
- Claiming @Throws makes Kotlin enforce checked exceptions
- Saying it wraps or rethrows the exception at runtime
- Thinking it affects Kotlin callers, not just Java interop
- Believing Kotlin has checked exceptions like Java