9 ms·
> I have heard that Java's checked exceptions are now seen as an important, failed experiment. Sadly, this is what people often say these days, I still think t
by sgift 10y ago
> I have heard that Java's checked exceptions are now seen as an important, failed experiment.
Sadly, this is what people often say these days, I still think they provide far more value than unchecked exceptions. I really liked it when I didn't have to provide any exception signatures and didn't have to think about where to catch them. I didn't like it so much anymore when unchecked exceptions started crashing my code, because there were exceptions thrown at points I never expected them to be thrown.
Either no exceptions or checked exceptions, but unchecked? My head :(
- silvestrov 10y agoThere are almost always the possibility of exceptions: you can get NullPointerException, OutOfMemoryError, ArrayIndexOutOfBoundsException, etc. There is a log of exceptions that derive from RuntimeException. You must always assume that code in the exception handler can fail unless you have written every single line and it allocates no memory at all.
- sgift 10y agoAll these exceptions are basically errors in your code, which is the reason they are runtime exceptions in the first place. The API needs a way to tell you that you produced a bug (because the type system, programming environment, etc. isn't advanced enough to prevent that case), but it doesn't have to bother you with writing code to handle that case: If it happens at production time you have a bug. Fix it. Don't try to work around it.
- ivan_gammel 10y agoNot all. Some of them are related to execution environment of an application, not to your code, and in this case developer may actually have something to do to adapt to the environment, rather than simply crashing.
- sgift 10y ago> Not all. Some of them are related to execution environment of an application, not to your code Let's say "more or less all": Yes, if there's an OOM because the system has not enough memory at all you maybe have to tell the user what to do instead of just crashing because the environment failed you, but in almost every other case the moment you accept the environment as parameter it becomes part of your code: If someone gives you a null object you can throw an IllegalArgumentException and show the calling program that it misused your API, but if you accept null and then call some method without checking for null the NPE you get is your bug, not that of your caller. Edit: Rewritten to make my point clearer.
- specialist 10y agoI still don't understand the complaint against checked exceptions. I've concluded that unchecked exceptions (above the runtime) and exception chaining are painful artifacts necessitated by using overwrought frameworks like Spring, J2EE, JPA, etc. Most useful anti-checked exception TL;DR I've gotten is "What do you do when your code can't act (recover) on a checked exception, like some library fails on I/O?" My answer remains "I handle it." After demo'ing my code, buddies conceded that my strategy works because I'm coding "close to the metal". In that case, it was an ETL/workflow engine (framework) that used hand-coded state machines (eg get next, data error, retry, restart). Looking forward, I'm keen to learn Erlang and Elixir. I have the impression they would provide for free all the error handling and recovery I painstakingly hand-coded.
- pekk 10y agoThe complaint is that it adds a lot of noise as people are forced to write handlers for exceptions they're not interested in, and these handlers are typically empty.
- int_19h 10y agoChecked exceptions don't play well with high-order functions, and basically anything else where one piece of code is calling into another piece such that it doesn't know what it is at compile-time (dynamically loaded extensions, DI, UI event handlers, and even plain old virtual methods in many cases). Basically, at those boundaries, you either have to say that the called code can throw anything - but then what about your own contract? you will either have to swallow everything; or rethrow everything, making it a part of your contract; or wrap everything in an exception type that you declare vas part of your contract, which is really a disguised version of rethrowing that doesn't add any meaningful value. Or else you say that the callee cannot throw anything, and then it is forced to swallow exceptions at the boundary. Here's a very simple example of how it affects design: try implementing Java's List<T>, or even Iterable<T>, on top of a file. Something really simple, like one string element per line. You'll find that it all works, except for error handling - because every read can fail, and neither List.get() nor Iterator.next() let you throw an appropriate exception type. In contrast, in .NET, File.ReadLines will happily return an IEnumerable<string>, which will throw IOException when a given line couldn't be read - because IEnumerator is not limited with respect to what exceptions it cannot throw. To properly deal with this problem, you need value-dependent types. Then you can do things like write, say, a generic implementation of map() that takes any random sequence, and throws the same exceptions that said sequence can throw when it's iterated.
- Joeri 10y agoI don't typically find much value in an exception, checked or unchecked, that is passed up the chain more than one step. The ability to intelligently handle an exception other than by logging/swallowing it decreases very quickly with every step up the call chain. If I don't know what to do with an exception in a particular method it is highly unlikely the caller of that method will have more of a clue. That's why I tend to catch all exceptions and then either produce a fallback value, or signal back to the caller by returning an Optional (if the only useful thing to tell it is that it wasn't possible to produce a value) or by throwing a new specifically tailored exception and making that checked. In either case, the caller must be explicit about what they want to do when things go wrong.
- ivan_gammel 10y agoThere are few specific cases, when you actually can do something after multiple returns, and they belong to RuntimeException hierarchy. I've seen good example of it just few hours ago, when my IntelliJ WebStorm (Java application) signalled, that it doesn't have enough memory (OoME) and suggested to update Xmx config setting and restart. Apparently, such exceptions should be handled at the root of execution stack, but sometimes, like in this case, there are ways to handle them with minimal damage.
- voodootrucker 10y agoThat's why you allocate every resource in a try-with-resources block, and let the exception fly all the way up to the top level of the stack, where you log it. Everything is unwound, everything is safe, special logic and wrapping not required (though wrapping can be valuable if there is information to add along the way).
- cbsmith 10y agoNah, they're pretty much a flaw. The idea of having compile time checks for exceptions is a good one, but the assumption that the callee understands what should be checked/unchecked by the caller is... not well supported by the evidence.