When Java introduced checked exceptions — where the compiler enforces that most exceptions are either caught or declared to be thrown — it was a fairly new idea. Java was a much safer language than most of its predecessors: all behaviour defined and consistent across all platforms, and many features intended to prevent crashes, unexpected behaviour, or fragile coding. So checked exceptions fitted in well with the language's philosophy.
But in the years since, many people have come to the conclusion that checked exceptions were a mistake. I'm not totally convinced, but here are some of the reasons:
They're verbose. It's common for methods to include many try
…catch
blocks, and/or to declare many exceptions. Also, if there are 6 levels of method call between where an exception is thrown and where it's caught, the exception will need to be declared by 5 methods.
Kotlin does away with much of Java's boilerplate, and doing away with checked exceptions fits in with that.
They encourage bad practices:
- Trying to handle exceptions in the wrong place, i.e. at the wrong level of abstraction, where nothing useful can be done.
- Pointless
catch
blocks (especially dangerous ones which do nothing but logging the error).
- Catching/declaring
Exception
instead of the specific subtypes.
- Cheating by wrapping checked exceptions in unchecked ones such as
RuntimeException
.
They increase coupling between modules. If you're using a library method which adds a new exception, then all code calling that method needs to be updated to handle or rethrow it.
They require exceptions to be translated between different levels of abstraction. (For example, a DB-access layer might have to convert a socket-timeout exception into a database-unavailable exception.) This is tedious, but necessary to avoid exposing implementation details.
They don't work well with inheritance. If the method you're implementing/overriding isn't declared to throw a particular checked exception, then your implementation can't throw it either.
They don't work well with lambdas. In Java, lambdas are implemented using Single-Abstract-Method interfaces, and so those methods must either declare the possible exception (in which case every usage must handle or declare it), or the lambda body must catch the exception. Both options greatly increase the conceptual weight as well as the code needed to use lambdas, destroying the conciseness which is one of their main benefits.
Kotlin's implementation is fairly similar (though it uses its own KFunction
interfaces), and would suffer the same problems.
With all these problems, it's clear that checked exceptions are a mixed blessing at best. And I can see why Kotlin has done away with them.
I do worry that it may result in programs that are less robust (and less well documented). But in the two years I've been using Kotlin, I haven't seen any obvious cases of this. So I'm holding off judgement for now :-)
(See also this question.)
As to how to handle your particular case, I suggest you do the same as you'd do if Kotlin had checked exceptions: see what exceptions the method you're calling can throw, work out how/where best to handle them, and handle them! Just because Kotlin isn't forcing you to do so, doesn't mean it's not still a good idea!