6 ms·
Getting rid of checked exceptions would be very beneficial for Java's popularity. No modern JVM language has kept that annoying feature. Just stop checking them
by seunosewa 1y ago
Getting rid of checked exceptions would be very beneficial for Java's popularity. No modern JVM language has kept that annoying feature. Just stop checking them at compile time, or make it an optional feature.
- Defletter 1y agoChecked exceptions are not the problem. In fact, I don't think there should be ANY unchecked exceptions outside of OOM and other JVM exceptions. I will die on this hill. The actual problem is that handling exceptions in Java is obnoxious and verbose. I cannot stress enough how bad it feels going from Zig back to Java, error-handling wise. If Java had Zig-style inline catching, there wouldn't nearly be as much humming and hawing over checked exceptions.
- xmodem 1y agoA hot take I have is that Java's checked exceptions - which everyone hates - are semantically very similar to Rust's Result<T, E> and ? error handling - which is broadly liked. The syntax makes or breaks the feature.
- lock1 1y agoIt shares the same important property (short-circuiting, explicit & type checkable) with Rust's `Result<>`, yes. I don't think it's a direct equivalent though - Java's exception creates stack trace by default - Type erasure which prevents you from doing anything "fancy" with try-catch + generic's type parameter - You can only throw something that extends `Throwable` rather than any type `E` - etc But yeah sure, if Java somehow provided a standard interface & an associated operator like Rust's Try trait to handle checked exception, it would probably have a much better reputation than it has now.
- redditor98654 1y agoA while ago, I had attempted to do it the Rust style with a Result type in Java (where it is called Data oriented programming) and the result is not great. I was fighting a losing battle in a naive attempt to replace checked exceptions but still retain compile time type safety. https://www.reddit.com/r/java/s/AbjDEo6orq https://www.reddit.com/r/java/s/AbjDEo6orq
- Defletter 1y agoYeah, Java's generic-type erasure makes result types difficult, though as you mention in your code example, this can be mitigated some using switch guards. But you could also go into another switch: switch (result) { case Ok(var value) -> println(value); case Err(var ex) -> switch (ex) { case HttpException httpEx -> { // do something like a retry } default -> { // if not, do something else } } }
- lock1 1y agoInteresting anecdote. At $DAYJOB, I'm currently migrating a non-performance sensitive system to a functional style, which requires defining basic functional types like Option<> and Result<>. So far I think it works pretty well and certainly improves edge case handling through explicit type declaration. My current stable incarnation is something like this: sealed interface Result<T,E> { record Ok<T,E>(T value) implements Result<T,E> {} record Error<T,E>(E error) implements Result<T,E> {} } Some additional thoughts: - Using only 1 type parameter in `Result<T>` & `Ok<T>` hides the possible failure state. `Result<Integer>` contain less information in type signature than `Integer throwing() throws CustomException`, leaving you fall back on catching `Exception` and handling them manually. Which kind of defeats the typechecking value of `Result<>` - A Java developer might find it unusual to see `Ok<T,E>` and realize that the type `E` is never used in `Ok`. It's called "phantom types" in other language. While Java's generic prevents something like C++'s template specialization or due to type erasure, in this case, it helps the type system track which type is which. - I would suggest removing the type constraint `E extends Exception`, mirroring Rust's Result<> & Haskell's Either. This restriction also prohibits using a sum type `E` for an error. - In case you want to rethrow type `Result<?,E>` where `E extends CustomException`, maybe use a static function with an appropriate type constraint on `E` sealed class Result<T,E> { public static <E extends Exception> void throwIfAnyError(Result<?,E>... ); } - I like the fact that overriding a method with reference type args + functional interface args triggers an "ambiguous type method call" error if you try to use bare null. This behavior is pretty handy to ensure anti-null behavior on `Option.orElse(T)` & `Option.orElse(Supplier<T>)`. Leaving `Option.get()` as a way to "get the nullable value" and a "code smell indicator"
- HexDecOctBin 1y ago(I am primarily a C developer) What is the problem with Checked Exceptions? Don't they just provide type checking? I would think that developers would want to know which function might or might not execute a non-local goto in middle of execution and handle that properly, since debugging that will be a mess.
- xmodem 1y agoPart of it is an ecosystem thing. It's a lot better now, but there were times when libraries would throw a variety of checked exceptions that usually couldn't be handled sensibly other than by being caught and logged by your top-level exception handler. This forced you to either (a) pollute many methods on many layers of your class hierarchy with `throws X`, potentially also polluting your external API (b) catch, wrap and re-throw the checked exception at every call site that could throw it (c) Use Lombok's `@SneakyThrows` to convert a checked exception into an unchecked one. Which they advise against using on production code, and which I have definitely never used on production code. There are specific situations where checked exceptions work well - where you want to say to specific code "I can fail in this specific way, and there is something sensible you can do about it". But those are fairly rare in my experience.
- ahoka 1y agoIn practice there are problems: Everything can throw IOException technically which you need to handle. There are non checked exception anyway, so there might be exception that are thrown anyway. It's a mess and there is a reason no other mainstream language uses them, even if Java people don't like that fact.
- peterashford 1y ago"Everything can throw IOException technically which you need to handle" wut?
- zmmmmm 1y agoA lot of that comes back to the lack of power in the type system (type erasure, lack of union types, etc). If all that code throwing IOException could express better the type of fault, and if the error handling could them in a more nuanced, less awkward manner, it would be much better than it is.
- PhilipRoman 1y agoI think checked exceptions are fine, they just haven't updated them along with other features. We now have expression based switch, why not have expression based try-catch? The other major problem is inability to pass them through the new functional interfaces, since they usually don't have anything like `<X> throws X`. But this could be solved by an Optional-like type.
- zmmmmm 1y agoit's is kind of interesting that we are in a phase where Rust is the "cool" language even though it has a similar kind of feature. I wonder which way it will age.
- peterashford 1y agoObviously YMMV, but I like checked exceptions
- elric 1y agoI disagree entirely, but I'd love to hear your arguments (other than vague allusions to "popularity" and other languages). Improved checked exception handling in Streams would be nice, but that's my only gripe with them. They force you to stop and think, which is a good thing. There are some checked exceptions that should probably be unchecked, like UnsupportedEncodingException thrown by ByteArrayOutputStream::toString which takes a charset name. I'm sure there are other subclasses of IOException that could be an IllegalArgumentException instead. But those few inconveniences don't invalidate the concept of checked exceptions.
- peterashford 1y agoI'm 100% with you - Streams is the one area where I think they dont pay well. Everywhere else, they're fine
- seunosewa 1y agoWhich checked exceptions do you declare or enjoy having to handle in your codebase?
- peterashford 1y agoI declare any which I'm not handling at the point they're raised. Unless I'm just ignoring them in which case I just declare methods throw Exception.
- smrtinsert 1y agoThere should be a middle ground where the IDE could generate your exceptions for you based on unchecked exceptions. Dunno what to call that but dealing with checked exceptions in the IDE is so much easier than manually reading docs for runtimes. Yes you could vibe + c7 it these days, but still the whole thing feels nicer with checked exceptions.
- forinti 1y agoI would like some sort of pragma that would allow me to ignore all checked exceptions in a file. Something like "use nocheck;" and then all methods would implicitly throw Exception. Sometimes I want to write a small program for a one-off task and handling Exceptions is absolutely unnecessary.
- DarkNova6 1y agoThis is a typical opinion to have. This is also an uninformed opinion. All Java needs is better syntax to handle exceptions. Nobody wants to open a whole block to handle an expected exception. ``` switch (f.get()) { case Box(String s) when isGoodString(s) -> score(100); case Box(String s) -> score(50); case null -> score(0); case throws CancellationException ce -> ...ce... case throws ExecutionException ee -> ...ee... case throws InterruptedException ie -> ...ie... } ```
- deleted 1y ago[deleted]