What is the difference between checked and unchecked exceptions, and how do Kotlin and Swift handle this?
LanguagesMid-level
In shortIn Java, checked exceptions must be caught or declared with throws, and unchecked ones (RuntimeException) don't. Kotlin has only unchecked exceptions. Swift marks functions with throws and every call with try, but errors aren't typed unless you use typed throws.
Model answer
Java splits exceptions in two:
- Checked (extend
Exception): the compiler forces callers to catch them or declarethrows. Meant for recoverable situations the caller should plan for, likeIOException. - Unchecked (extend
RuntimeException): no enforcement. Meant for programming errors, likeNullPointerExceptionorIllegalArgumentException.
The idea is good, but in practice checked exceptions don’t work with lambdas (stream().map(this::load) can’t throw IOException), they leak implementation details up through layers, and they encourage empty catch blocks. Modern code often wraps them at the edges (UncheckedIOException), always keeping the original as the cause.
Kotlin has no checked exceptions at all. For expected failures, Kotlin code often returns null or a sealed result type instead, and uses @Throws so Java callers can catch exceptions.
Swift takes a middle path: throws in the signature and try at every call site make failure visible, but the error type is any Error unless you use typed throws (throws(ParseError), Swift 6). Swift errors are ordinary return values under the hood, so throwing is cheap.
In all three, cancellation (CancellationError, CancellationException, InterruptedException) travels through the error path and must be propagated, not handled as a failure.
What they're looking for
The Java rule and the reason behind it (recoverable vs programming errors), the practical problems with checked exceptions (lambdas, leaking details), how Kotlin and Swift differ, and good habits like keeping the cause when wrapping.
Common mistakes
- Claiming Kotlin has checked exceptions, or that Swift errors are exceptions with stack unwinding costs like Java's.
- Recommending catch (Exception e) {} or wrapping without the cause.
- Not knowing that lambdas in streams can't throw checked exceptions.