3 ms·
I haven't really been in the java space for a while now, but I recall there being a fair bit of criticism[1][2] of checked exceptions over the years. [1] https
by msluyter 16d ago
I haven't really been in the java space for a while now, but I recall there being a fair bit of criticism[1][2] of checked exceptions over the years.
[1] https://www.javacodegeeks.com/2026/01/javas-checked-exceptions-the-20-year-experiment-that-failed.html https://www.javacodegeeks.com/2026/01/javas-checked-exceptio...
[2] https://reflectoring.io/do-not-use-checked-exceptions/ https://reflectoring.io/do-not-use-checked-exceptions/
WRT magic, I've generally thought that was a result of frameworks - Spring, for example. In the past, my feeling was that these impose a sort of meta/configuration language that itself is not checkable at compile time, so you'd get weird runtime errors that are somewhat inexplicable. This was like... 2018 though, so perhaps things have improved.
- voidfunc 16d agoChecked exceptions are controversial mostly because a lot of the core APIs use them in places where it's pointless to check, like IOException. Using them correctly can be great tho.
- PaulHoule 16d agoMostly I think they are a mistake, like in ordinary application code instead of catching close to the throw you want to do a lot of try { ... } finally() { ... } to make sure things get torn down that have to be torn down and let the exception go to the top of the unit of work and probably to whatever drives the work unit. You can probably do better than logging the raw exception and moving on to the next work unit but you can do much worse. That is, you want a default "sloppy" error handling approach that's correct that you can do without thinking and avoid other kinds of "sloppy" coding encouraged by checked exception such as catching exceptions locally without doing the right thing globally. Occasionally though I have built something really sensitive, like an authentication filter for a web site which has at least 5 ways to log in and in that I have a hierarchy of exceptions and use checked exceptions heavily to document all the ways things can go wrong and felt like "the type system really has my back here" but that is like 5% of the Java I write.
- samus 15d ago> avoid other kinds of "sloppy" coding encouraged by checked exception such as catching exceptions locally without doing the right thing globally. That's a code style and code review issue; each project has so set standards regarding how errors are dealt with and enforce them throughput the codebase.
- PaulHoule 15d agoOf course! But from a quality standpoint there are three concerns: (1) Do you actually do the code review, do you actually enforce the style? I worked on a Scala project where the dev manager thought it was preferable to handle errors with monads and would be vociferous about what a great practice that was compared to exceptions and that code review was central to how we do things... but if you looked at the code most of the time errors just got dropped silently and that was the same for many practices that the dev manager told me were doing but that we don't. He still posts on LinkedIn complaining about other dev managers who say they do code review but really don't. Practically that code didn't consistently give the right answers and poor error handling was one reason, another was that they never really understood that teardown was just as important as initialization. (2) Is your documented practice correct? Is it really doing the right thing? In a lot of cases there really is a right and wrong way to do things (e.g. uv resolves Python dependencies properly, pip doesn't) but it's less clear in error handling, like sometimes things went wrong and there is no way you can make it right and you can do the best that you can. The global nature of the problem is vexing. Like an IOException might really be a BackhoeCutAFiberSomewhereInWisconsinException and a segmentation fault is occasionally a YouAskedForAOneAndGotAZeroInsteadException and it's not just academic because, given an exception, you want to answer questions like "Should I retry this operation? How long should I wait before I retry this operation?" (3) Is this practice something you can sustain? How hard is to do? How much cognitive load does it add and how does it interact with other practices? "Throw up as much as you can", "tear down in finally {}", "otherwise handle local consequences of errors and rethrow" and "really catch errors at the drivers of units of work" is a practice that really works in many languages and is pretty easy to do right, even code that is written without a lot of care will do the right thing or something close by default. I've seen a lot of "no plan for error handling" or "bad plan for error handling"... like I was traumatized by the first C program I saw in a 1984 issue of Byte magazine which was using errno to handle errors which vastly complicated very simple code because the error path was intimately wound with the happy path and in cases like that there tend to be bugs in both of them. When I saw Exceptions in Java I remembered that old C program and thought "I love this!"
- ndriscoll 16d agoScala's ZIO also demonstrates that they're a great idea and can be perfectly ergonomic, but you need type inference, which Java devs were resistant to for a long time (maybe still are? I remember lots of "how will I ever know what `val a = new Animal()` is???"). If you infer the exception type, they're basically invisible except for when you forget to have some place in your program to handle them, which is exactly what you want.
- dmux 16d ago>in places where it's pointless to check, like IOException Can you explain why this is pointless? In my mind, this being a checked exception would hopefully be a hint that I should think about this failure-case and make an explicit decision whether to handle it or not. Network connection failed? Maybe I retry. Maybe I store that data somewhere else as a fall back. Isn't this similar to Go programmers needing to check if err is not nil?
- mrkeen 16d agoI don't think I can recall a time where I routed-around-the-damage on the basis of a particular typed exception. As soon as you consider retrying a network failure, you immediately need to start thinking about distributed systems failures, idempotency, and all that good stuff. As soon as you start thinking about the above, it becomes immediately obvious that low-level calls should not be able to decide to re-run themselves.
- dmux 16d ago>I don't think I can recall a time... I appreciate that there is a _ton_ of different experiences out there when it comes to solving problems, but I _have_ encountered exactly the case I was describing, which is what led me to my original question. Isn't the fact that it was a checked exception that led you to "consider retrying a network failure, you immediately need to start thinking about distributed systems failures, idempotency, and all that good stuff" worth it as opposed to an unchecked exception you may not realize is being thrown?
- BoppreH 16d agoI'd argue that checked exceptions are still worth it, even though all the problems pointed out do exist. And that's because it works to inform consumers of what a producer is doing. Haskell has the IO and Maybe monads; Java communicates the same information through IOException and other domain exceptions. Many times I've decided to switch from one function to another, or even an entirely new library, because the checked exceptions told me that it was doing far more than I expected, and I was not comfortable introducing those new failure modes. It's far from perfect, one still has to handle nulls and wrapped/merged exceptions, but overall I like this language feature.