I am a Java developer and I am learning Kotlin, which is very exciting to me. But when I found the exception is unchecked in Kotlin, I have some concerns.
I agree in some cases the checked exception is not good and annoying, such as the samples in Kotlin’s tutorial.
But when you build large system with several tiers and multiple modules, checked exception is part of the interface definition. It’s not just “a compile-time vs. run-time checking issue”. Lower-end module has the responsibility to hide the internal detail, such as IOException, FileNotFoundException, and translate it to other type of Exception. That’s the standard in Java. And everything is built on checked-exception to specify which kind of Exception to be thrown. Otherwise, upper level code may get weird exception, which may be handled by other modules. And when project grows bigger, more different types of exception may be thrown. I can foresee the final solution is to catch any “Throwable” to make client code stable, no matter if any exception will be thrown or not.
So could Kotlin have checked exception in future? At least, give compiler an option to check unhandled exception and treat them as warnings.
Adding checked exceptions to Kotlin would be a major breaking change, and as such, would require very strong new arguments in favor of it. At this time, given the experience of many different languages which do and don’t include checked exceptions, and the fact that large stable systems with several tiers and multiple modules have been built in languages which do not include any form of checked exceptions, we do not expect such new arguments to ever appear.
As for optional warnings, this may be possible, but it’s not on our roadmap for Kotlin 1.1.
Quite some experience shows that checked exceptions can be a major pain in the neck, in particular with a functional style of programming. Say you have a visitor for a list. The list code cannot know anything about your visitor, but the code that causes the visits obviously would. Suppose you want to throw an exception in some cases from inside the visitor. Of course you can use a RuntimeException, but if the exception is actually not yours by say an SQLException or the like, you can’t. In that case you will have to write 2 separate exception handlers. First in the lambda you will have to write an exception handler that rethrows the exception inside some wrapper. Then in the outer code you will have to throw catch the wrapper, and throw the original.
In short, checked exceptions are very bad with functional programming, and only rather bad from a library writer perspective. It certainly causes excessive catch/rethrow wrapped issues.
I definitely agree with you, pdvrieze. In some cases, the checked exception is very bad, especially in FP, maybe.
But let’s say there are some APIs of service layer without checked exception, which means these APIs could throw anything. An API may do the money transfer but it may throw an exception about some internal file not found to client code. Yes, the API author should fix it but without compiling hints and with code growing, people may make mistake. I think that’s also why we love strongly-typed languages, which could avoid a lot of such kind of issues.
We may not have checked exception in Kotlin but compiling warnings could help a lot.
Bearing in mind missing checked exception, would it be a good practise to catch exceptions as soon as possible and return null / an object with a status? Otherwise it’s really difficult to track all the places where an exception could be thrown and it’s easy to leave it unhandled.
For example, file writing function almost always should communicate an error up to the calling code (just because it’s quite a low-level function, that can’t handle it properly). In java this function can throw an IOException and you must catch it on the calling side. In the same time in kotlin it’s easy to forget try-catch block on calling side. So should this function just catch IOException thrown from system IO-methods and convert them to a return value?
So does kotlin encourage us to use exceptions only for communicating unexpected runtime exceptions, that generally should not be handled anyway and use other methods otherwise? @yole could you comment on this? It may be worth mentioning in the kotlin docs also. Currently there is only explanation why there is no checked exceptions in kotlin, but no any words about recommended alternatives and working with an existing java code.
In my opinion, @Throws annotation solves the problem you are talking about. You do not need for exception to be present in the method signature, one could simply look at annotations. Then one can use IDE warning if the exception is declared in annotation but never evaluated. I do not know, maybe such inspection already exists somewhere.
Probably an IDE warnings can help, but I have not seen any similar warnings yet and thought @Throws annotation is more about java interoperability. There can be also other solutions, like returning null or status object. That’s why I wonder if there is a best practise / community standard.
I do not think that status objects are adequate replacement for exceptions. Of course, it all depends on what you call “status”. In Java it is a bad idea to use exceptions to report status of normal completion of operation for many reasons. So, I would say, only use exception when you have abnormal termination of some operation.
To define some “special return values” for exception cases will not work. Such kind of code will be very hard to maintain. The root cause is it’s not part to API definition and it can’t be enforced in coding.
And agreed! Kotlin team should provide the best practices.
@darksnake, I agree it’s not the best replacement, but what options do we really have?
Yes, exceptions should not be used for status reporting in general, but checked exceptions are often used for reporting predictable errors (such as IOExceptions, they usually do not mean any abnormal things like Runtime exceptions do). I believe in java that is the difference - unchecked exceptions are for abnormal situations and should not be generally handled at all (just like in kotlin), but checked exceptions are for reporting ‘normal’ errors, that actually can happen (and often will happen!). And I can’t find any good alternatives for reporting such type of errors in kotlin. And moreover, even if you do not throw any exceptions in your code, currently it’s easy to forget try-catch block when calling java functions with checked exceptions and get a crash.
I believe the best option would be to support checked exceptions, but with an option to convert it to runtime exception easily with one command (without an ugly try-catch-throw block). That is when we usually want to use empty try-catch block in java with a comment ‘should never happen’, which really means ‘should never happen, but if it happens something really is going wrong, throw a runtime exception’.
Am I missing something? I believe most kotlin developers should face this problem, how do you handle it?
I do not really see the problem. Kotlin supports the whole java exception hierarchy. The only difference is that compiler won’t generate a error if those exceptions are not rethrown in calling method. The developer still can explicitly catch those exceptions and evaluate them, otherwise they will be automatically rethrown as runtime exceptions.
Specifically for “can’t happen” case, kotlin standard library has error(...) method which inlines java IllegalStateException.
Java checked exception are incompatible with lambdas, so they were dead long before kotlin arrival. I think that you can open a ticket for IDE inspection for declared and not evaluated exceptions, Maybe there is already one, but I did not found it.
Personally, I just usually wrap parts where exception could be thrown, but I want it to be reported as a warning rather then crashing program, in unspecific try-catch. I do not work in enterprise though, there could be different rules there.
Thanks, @darksnake. I agree, such an inspection together with @Throws annotation can solve the problem.
The fact that there is still no such inspection made me think there is another common solution. I will look into ticket creation.
Bad practice. The correct point to handle exceptions is a central exception handler that normalizes how to treat them. An exception is something that does NOT let your Touring Machine to continue normal processing due to either one external failure (I/O exception) or some internal assert failure. It’s naïve to thing that a compiler warning about some checked exception will help you at all and promoting exceptions handling randomly spread in the code (like checked exceptions do) is an antipattern.
I hope Kotlin developers will never introduce such mistake in the language.
In the mean time, I just wrote a “nano”-library promoting exception handling best practices:
Checked Exceptions help a lot, I still didnt found a good solution for them in Kotlin.
They force you to check Errors that can happen on running a method at example, there is no way to forget the checks and most important you can check them partly in the middle way or pass them to a higher hierarchy
I have 3 classes:
DropBoxService: Does Dropbox interactions
LevelManager: Make some thing with the File when download was sucessful
UIScreen: Calling Level Manager
I can handle Exceptions from DropBoxService in LevelManager ot let them be handled from UIScreen (like showing error Message)
I didnt find a way to solve that in a nice way in Kotlin yet