If you annotate a Kotlin function with @Throws, does it force other Kotlin code to catch the exception? Explain what changes and what does not.
answer
- One-way bridge Kotlin → Java only
- Changes JVM signature, not Kotlin checking
- Kotlin callers still need no try/catch
- Runtime behavior identical with/without it
- Removing it can break Java callers
basics
~10 sNo. @Throws never forces Kotlin callers to do anything — Kotlin has no checked exceptions. It only changes the generated JVM method signature so Java callers can catch or declare the exception.
solid answer
~40 s`@Throws` is a one-way interop bridge: Kotlin → Java. The only thing it changes is the **bytecode signature** of the generated method, adding a `throws` clause. Kotlin callers are completely unaffected — they are never required to wrap the call in `try/catch` or to declare anything, exactly as before. The runtime behavior is identical with or without the annotation: the same exception is thrown at the same place. So the annotation is invisible to the Kotlin type system and the Kotlin compiler does no flow analysis based on it. Its sole audience is the Java compiler, which uses the `throws` clause to permit (or require) handling of checked exceptions. A common mistake is to expect `@Throws` to give Kotlin Java-style enforcement; it does not, and Kotlin has no mechanism to enforce checked exceptions.
go deeper
States that Kotlin callers are not forced to catch and that the annotation is Java-facing.
Separates 'what changes' (JVM signature, Java callers) from 'what does not' (Kotlin callers, runtime).
Adds that removing the annotation is a source-compatibility risk for Java callers and explains why Kotlin dropped checked exceptions.
Treats @Throws as part of the binary/source-compatibility contract of a published Java-facing library and weighs it in API governance.
## What `@Throws` is and is not `@Throws` is an **interop annotation**. It tells the Kotlin compiler to add the listed exception types to the **`throws` clause of the generated JVM method**. That is the entire effect. It is consumed by the **Java** compiler when Java code calls the function; the **Kotlin** compiler does not use it for any checking. ## What does NOT change - **Kotlin callers** are never forced to `try/catch` or to declare the exception. Kotlin has no checked exceptions, and `@Throws` does not add any. - **Runtime behavior** is unchanged: the same `Throwable` is thrown from the same line, whether or not the annotation is present. - **Kotlin compiler flow analysis** ignores it — there is no warning if a Kotlin caller does not handle the exception. ## What DOES change - The **JVM method signature** gains `throws X, Y` for the listed classes. You can verify this by decompiling the `.class` or viewing the Java-facing stub. - **Java callers** can now `catch` the listed checked exception without the *"exception never thrown"* error, and may be **required** to handle it if it is checked. ## Demonstration ```kotlin import java.io.IOException @Throws(IOException::class) fun load(): String = throw IOException("boom") fun kotlinCaller() { // No try/catch required — compiles fine. // The IOException still propagates at runtime exactly as before. val s = load() } ``` The Kotlin `kotlinCaller` needs no handling. A Java caller, however, must deal with the checked `IOException`: ```java // Java: must catch or declare String s; try { s = FileKt.load(); } catch (IOException e) { /* required */ } ``` ## Why Kotlin made this choice Kotlin's designers concluded that checked exceptions in large codebases often lead to **boilerplate `try/catch` blocks that swallow or rethrow** without adding value, so Kotlin dropped enforcement. `@Throws` exists only so Kotlin can still **participate cleanly** in Java's checked-exception world at the boundary. ## Practical takeaways - Use `@Throws` only on **Java-facing public APIs**; it is noise on internal Kotlin-only code. - Do not rely on it for safety inside Kotlin — document and handle exceptions explicitly instead. - Removing it can be a **binary-incompatible** change for Java callers that declared the checked exception (their code may stop compiling).
- Does removing @Throws later risk breaking anyone?Yes — Java callers that wrote 'throws IOException' or caught it may fail to compile once the clause disappears, so it is a source-compatibility concern for the Java surface.
- Will the Kotlin compiler warn if a Kotlin caller ignores an @Throws-annotated exception?No. The Kotlin compiler does not do any flow analysis based on @Throws; only the Java compiler reacts to the throws clause.
saying these in an interview costs you the question
- Saying @Throws forces Kotlin callers to catch the exception
- Claiming it alters runtime/throw behavior
- Thinking the Kotlin compiler warns based on it
- Not realizing removal can break Java compilation