One of the biggest flaws in C#, in my experience, is lack of checked exceptions. As an example, I wrote some very good code, carefully tested it, made it work flawlessly, then suddenly it started crashing. What happened? Someone made a change in a function I was calling, and it started throwing a new exception. This would have caused a compile error in Java, not a crash.
Which really is a zero sum game. The code still breaks the same way, but the checked exception gets eventually wrapped in an unchecked one. We still would have the situation that someone changed the behavior of the function in a way that is incompatible with your usage.
That bug should have been caught by tests, code reviews and good communication.
> One of the biggest flaws in C#, in my experience, is lack of checked exceptions.
I couldn't disagree more. Checked exceptions in Java have ruined a generation of programmers.
The truth is, under checked exceptions, to satisfy the compiler the function that you called would declare that it throws a SomeModuleException and the programmer who wrote that function would put all his code in try/catch block that catches all errors and rethrows a SomeModuleException with the real exception passed as the cause.
On the other hand, in lots of application code, there's often not much to do other than crash or abort the request, and this can often be safer than trying to proceed along code paths that are almost always under-tested. We've all seen Java code where a junior has decided to swallow an error without much thought. This obviously isn't true for every use case, but failing fast is often a pretty good policy.
I mean, maybe? Fun degenerate cases to consider: Someone throws a Environment.Exit(0) into a random library you are using, instant pain. Someone throws an infinite loop into a library you are using, similar instant pain.
There is no magic language trick that can prevent you from having to rerun all tests for your software if you update a dependency. Pretty much period.
(I say this as someone that isn't really opposed to checked exceptions.)
The trouble with checked exceptions is that they prevent you from easily extending classes or implementing interfaces that you don't control. Your new class might need to throw a checked exception not included in the method signature. So then you have to resort to hacks like wrapping the new checked exception inside a runtime exception.
You should catch any non specific exception in the last catch block, just in case. Thought that was the standard. Java gets very messy in mixing checked and unchecked exceptions, I've seen a lot of devs just ignore the unchecked ones.
> Someone made a change in a function I was calling, and it started throwing a new exception. This would have caused a compile error in Java, not a crash.
Not necessarily. If it started throwing a new RuntimeException, it wouldn’t have. There are also sneaky ways to throw checked exceptions without declaring them, for example using Lombok’s @SneakyThrows annotation
Your code might have been very good, but it wasn't future proof. It sounds like your code would have been fine if you locked down the libraries you were calling to a fixed version or something.
One of the reasons I hate exceptions overall. Someone may add new ones, they break the control flow, they bubble up all over the place, etc etc. They are basically indomitable.
Exception based error handling is so bad and unsafe that adopting functional error handling with Either, Try etc as implemented by functional addon libraries for many languages, while not yet common, in time it will become the new default even in OO languages. (just like it's been the default in functional languages for decades)
Functional error handling types are much simpler, safer and more powerful.
Simpler because they don't rely on dedicated syntax- they're just regular objects no different to any other object.
Safer because unlike exceptions, they force callers to handle all potential outcomes, but no more. (no risk of ignoring errors and no risk of catching a higher level of error than desired, ubiquitous bugs in exception based error handling)
Powerful because they support map, flatmap, applicative etc, making it easy to eg chain multiple computations together in desired ways, which is unwieldy and bug prone when using exceptions.
> What is wrong about dedicated syntax
It adds complexity to the language! It could be that, when learning Java, Kotlin and any other language, we learn that methods return what they say they do... and that's that. No weird dedicated syntax and magic, special treatment for returning anything other than the happy path, and the HUGE complexity that comes with it, eg the dedicated syntax itself and how it behaves, differences between checked and unchecked exceptions, hierarchies of exceptions etc etc.
> Exceptions are easier
But that's the point, they're not.
Exceptions based error handling is unnecessary, hugely complex, doesn't compose at all, obfuscates or straight up hides what can go wrong with any given call, so leads to countless trivially preventable bugs... I could go on. And after decades of use, there's still no consensus about what exceptions should be or how they should be used. Exceptions are a failed experiment and I have no doubt that in ten years, Java, Kotlin and many other languages will acknowledge as much and move away from it the same way Joda Time outcompeted and replaced the horrible Java date and time library.
Checked exceptions are exactly analogous of Result/Either types. They are just built into the language with syntactic sugar, automatically unwrap by default (the most common operation), can be handled on as narrow or wide scope as needed (try-catch blocks), does the correct thing by default (bubbling up), and stores stack traces!
In my book, if anything, they are much much better! Unfortunately they don’t have a flawless implementation, but hopefully languages with first-class effects will change that.
Exception based error handling is unsafe when they are unchecked exceptions. Checked exceptions however are as safe as Either, Try, Monads, Applicatives or whatever.
You are forced to declare them in your method signature, the caller is forced to either handle them or rethrow them + declare them as well.
And I guess this is precisely why so many developers hate them; they don't like the extra work they have to do to catch all those edge conditions.
This is why we see so many empty catch blocks or upcasting to Exception or even Throwable; it is laziness.
I would also argue that checked exceptions are no more complex than Eithers, Try or Applicatives. Actually passing Eithers or Applicatives around everywhere can easily clutter your code as well, IMO it can be worse than checked Exceptions.
> Safer because unlike exceptions, they force callers to handle all potential outcomes, but no more.
Which is bad. In 99% of cases I have no specific error handling for the given problem. Just let the process crash or be handled by application server / framework.
Representing these kinds of error conditions in the code which I have no interest in handling is just noise.
That said, not modelling them in the type system is a mistake. But the model has to be useful - knowing what functions can or cannot throw is useful, knowing what they throw, less so.
(They are safe because of try-finally / try-with-resources)
> Safer because unlike exceptions, they force callers to handle all potential outcomes, but no more.
That's what wrong with them. Callers, in almost all cases, do not know what to do exceptional outcomes. So you force programmers into a situation where they're dealing with things they shouldn't be dealing with.
I actually quite like checked exceptions, and miss them in other languages. My biggest gripe with exceptions is that a few calls deep, you can no longer tell whether calling something might throw or not, and what type of exception it might potentially throw.
Checked exceptions are a leaky concept in Java.
The Java type system has no union types so you can not have a generics method that abstract more than one exception.
That's why Stream::map can not capture the checked exceptions properly.
I like checked exceptions in principle too, but Java's implementation of them is so bad that I hate them there. The first major mistake is that it doesn't support exception polymorphism (e.g., I wish you could pass a comparator to Arrays.sort that throws checked exceptions, and have that call to Arrays.sort itself then throw the same checked exceptions), and the second is that the standard library makes a bunch of exceptions checked that should be unchecked (e.g., IOException from close()).
Reading through the comments, I realize this may be a minority view - but I like coding for the happy path and letting exceptional states crash. I find languages like go a bit harder to parse quickly because I always have to "unwrap" the happy path from all of the mixed in error handling.
I'm sure I'd get used to it eventually, but I like that unchecked exceptions in Java are now an option!
If it's some random web backend, it's often fine to just let the error propagate as a 5xx. Many error cases wouldn't have a better solution anyway, and all that's breaking is a single page or resource load. (Of course on the frontend it might be nicer to show some kind of an error than just e.g. having frontend functionality silently fail.)
If it's a desktop application and you're crashing the entire application because wifi happened to drop or whenever there's anything your happy path didn't predict, that's going to be bad.
If it's some kind of an embedded thing and you're crashing an entire device because you didn't bother to handle cases that are outside of the happy path but entirely possible, I only hope it's not something important you're developing.
I'm fine with doing this on purpose, but without a system like checked exceptions, you do it without even really realizing you're doing it. Checked exceptions point out the errors and then let you decide whether it's something you should handle or let it crash. It makes for more stable software.
If you actually let it crash that's fine, but a lot of people just toss a catch (Exception ex) in there because they don't know what exceptions will happen and don't want errors that aren't actually a big deal to bring the system down. But the issue with catching everything, even if you log before continuing, is that the process may be in a bad state and you're just continuing with it like that. I got to see a couple database tables get absolutely mangled by a process that had an exception that was caught and logged. That was a pain to clean up since doing nothing more than restoring a backup would have lost the entire day's worth of business operations in that system.
This is what I like about Go and other more recent languages: Especially when networking or other IO is involved, things will go wrong. These languages don't try to circumvent this reality but instead embrace it by treating errors as very-first-class citizens. My error handling tends to be more thoughtful in those languages than in, say, Java.
This is an insightful interview, thank you for the link. I'm well read up on the topic, but this interview was still great and is a good perspective on the checked/unchecked debate.
The fact that Java has introduced UncheckedIOException, in my opinion, shows how some people in the Java community have come to believe that checked exceptions were a mistake (understanding that lambda forced the issue). There's probably not too much to be easily done at this point, but consideration for changing checked exceptions in the JDK to extend RuntimeException sure would be interesting.
Allowing unchecked exceptions in languages without explicit error handling or the return of error values is a mistake IMO! Makes it impossible to call a function safely
Exactly, C++ exceptions are horrible, you never know what throws what. Java made C++ exceptions better by making them explicit, so you always know what throws. Then Kotlin came and made everything a unusable mess (don't get me wrong, I love Kotlin, just hate that it doesn't have explicit exceptions).
I honestly think the best error handling strategy is employed by Zig, then Rust. they're very explicit while not getting in the way, you always know what throws what and what doesn't.
Rust has a little issue though, which is that people can make their functions return `Result<T, Box<dyn Error>>` which makes handling the returned error difficult, Zig does not have any of that.
I would argue the opposite: Junior and senior developers alike catch and swallow or log checked exceptions all over the place, making it impossible to know if your method call was successful or not.
I have a desktop application with a single exception handler wrapping it's event loop. The handler display the message to the user and returns the to loop. It's rock solid -- nothing can crash it. The user can try to save their file to some network share that just disappeared and when that fails just save again somewhere else.
But there is no such thing a safe function to call. Whether you handle errors by meticulously passing them around everywhere or not makes little difference.
(To clarify, i'm against exception based error handling, but removing checked exceptions in languages without other mechanisms of explicit error handling makes things more brittle. For example in kotlin, where some Java practices to throw all over the place are still in use, unchecked exceptions makes things worse. You wont know if a function will throw unless you inspect the code or trust it's documentation)
The friction between the benefits of detecting errors statically, handling them quickly, and the diversity of needs for error handling cannot be avoided with any fixed policy like "unchecked only".
This tool does remind us that checked exceptions in Java are a compile-time phenomenon only, so (non-compliant) compilers can be made to ignore them. Neat, but... helpful? It would certainly lock you into using the tool.
Instead, we need configurable policies for error handling, where the same code can be statically analyzed much more deeply (e.g., to include unchecked exceptions) or run more leniently (e.g., when exceptions are used only for flow control). Some of this might pertain to local declarations, and some might be policies of various scopes (per VM, per-package, or per call-chain), and would probably fold in assertions and fibers/virtual threads and some OS-sensitive behaviors. The goal would be to write the code once (with full disclosure, i.e., only check-able exceptions and assertions), but to reuse the same code under different policies.
Whether anyone wants to do the work of folding this into the VM as security privileges were is another question...
Agreed. I absolutely prefer checked exceptions since it forces devs and consequently business to develop requirements for possibilities. Lack of ambiguity helps me sleep at night. Potential runtime errors do not.
Putting aside the discussions about the necessity of checked exceptions (to which I feel unqualified to express my opinion), I believe the approach used by the OP article to remove them is not the best one:
- It requires modifying compiler arguments and putting some file in the local classpath! That's really not Java-ic. Is it?
- It is not transparent in the code. You cannot infer by looking at the source code that something has changed.
Since some time ago I use the NoException library[0] in my Java projects which achieves the same goal but without the above-mentioned issues. It can also be used to mimic Scala's Try construct.
Most other languages agree that checked exceptions are not good by not having them.
As for alternatives, Try/Result and similar monads have decent adoption even in Java, but personally I quite like the Kotlin philosophy [1] to not have generic error containers and either use runtime exceptions for errors that cannot be reasonably handled by the caller and encapsulate failures in the return type if they can.
Conceptually there’s not much difference between checked exceptions and multiple returns or returning a tuple with an error etc. The problem with Java is that the checked exceptions are too fine grained, so the signatures are brittle and non-composable. Everything should just throw an Exception and then use dynamic typing to figure the rest out, and then you wouldn’t have the problem that your toList method can’t compose with something that throws an unknown Exception subclass.
> Unchecked does not make any changes to your bytecode. This is possible because the JVM does not know about checked exceptions. It's been the compiler holding you back all this time.
This seems like a major improvement for Java readability as shown by the examples.
What I don't like is the examples of having to use Maven or Gradle to install it. Why does that have to be so verbose, and something written in another language?
Ha, yeh. At first I had the command line examples first, but everyone was going on and on about maven and stuff, so I figured that's what the audience wants.
[EDIT] I moved the command line stuff back to the top of the README. XML makes my eyes bleed too...
Checked exceptions turn out to be part of the API, meanwhile violating Liskov substitution principle and preventing some design patterns. This is because a superclass implementation might throw a checked exception, then its subclass not necessarily. However, if the caller refers the subclass instance via the superclass interface it must catch the exception, but if it refers via the subclass it must not catch, as that results in a compile error. So the point is that with checked exceptions you cannot replace an interface with any implementation, which should be possible in proper OO programming.
That’s not a Liskov violation. Changing the compile-time type of a local variable in the scope of the call site is not substituting the implementation of the referred-to object. Those are two different things.
As you correctly mentioned, if you leave the compile-time type of a variable unchanged, then assign a different object (one that belongs to a subclass that doesn’t throw the exception when you call its method) to that variable, and then call that same method, the compiler still forces you to catch. That’s the Liskov substitution.
I never forget reading the javadoc for Google Gson class com.google.gson.JsonParseException (extends RuntimeException):
This exception is a {@link RuntimeException} because it is exposed to the client. Using a {@link RuntimeException} avoids bad coding practices on the client side where they catch the exception and do nothing. It is often the case that you want to blow up if there is a parsing error (i.e. often clients do not know how to recover from a {@link JsonParseException}.
I have *completely* the opposite style: Throw checked for anything that can throw, except: null pointers and invalid arguments (e.g., negative port number). Why so much checked? The caller cannot hide from it. They are forced to ack it, else compiler error. At the very worst, they are free to rethrow as a wrapped RuntimeException (ugh).
When I write code in C#, I always left wondering: Does this method throw an exception (ignoring null pointer and invalid arguments)? It bothers me. And, I write that as someone who really likes C# -- it's a great language for my needs.
And, yes, I can appreciate that many people don't like the friction associated with checked exceptions. It does add a lot of visual bloat! Serious question: What are the alternatives that _communicate sufficiently_ through an interface? Honestly, I struggle to think of a better alternative, so I just live with it.
Just like the bad old days of integer return values used to indicate error state (C-like languages), you need to check every single call -- there are no shortcuts, especially with I/O. For me, it is similar with Java and C# when writing I/O code: You need to catch and correctly handle every (checked-ish) exception.
Checked exceptions are one of biggest mistakes Java ever made.
That said, patching compiler is not something I would do.
What I usually do is add unchecked exception class for every checked exception I had to "handle". So I have UncheckedIOException from standard library (handy!), UncheckedSQLException and so on and so on.
Yes, it causes more code, but Java is not exactly known for brevity, so be it. At least that way is not hacky in any way and actually used by Java standard library itself, so I'd consider it "idiomatic".
Neat. Reminds me of lombok in that it really only affects compile-time and makes for cleaner code in a way that many (but not all) developers would want.
Ugh Lombok! Literally everything it does is replaced by any competent IDE with auto-generated methods, with the added benefit of not requiring special build handling steps because the library can't play by the normal annotation processing rules.
There was maybe a time Lombok made sense. It does not anymore. Death to Lombok.
I don't want to remove all checked exceptions in random code, btw. Even though they're not common, it can be bad if they're unhandled in some cases. How can I know beforehand?
I'd like something to soften some of them, probably in a configurable way, in some builtin interfaces btw. E.g. many IOExceptions should really be unchecked.
Like the idea, but I probably won't use it. Yes, checked exceptions are annoying, but the correct place to fix them is the source. This compiler plugin blinds you. The ordinary ways to mitigate checked exceptions (wrapping them in unchecked exceptions) is ugly but its also explicit.
To the credit of the die-hard Java community, you all really seem to love and support even the most horrific syntax and awful language features. You love the pain. The rest of us are here for you... I promise software can be fun.
Checked exceptions are far and away the worst part of java and I'm glad that no other language I've personally encountered have them!
On a more real note, I work at a shop with a fair amount of java now and checked exceptions are definitely my biggest complaint. I hope we adopt this, I'm sure we won't, but I'm glad to see a little movement on what I feel is the crusty status quo in the java world.
Agreed, checked exceptions are awful. The idealists love them, the realest knows you can't write code up front handle every single exception case, and in most cases you aren't recovering from an exception anyways.
Especially the higher the level the code is the more potential lower layers that can fail. It's just not scalable to write code up front to deal with every single case. And most programmers don't care about failure, or working around it, just success.
On the other hand we do expect the unexpected and wrap failure prone code in try/catch so that we can log exceptions and keep the app moving. Figure out later if the ROI is there from enough failures to write special code to try to prevent and/or recover from a particular exception.
It's pretty much the same as it is in the checked exception world just with more code - in Java people handle the exception, log it and/or rethrow, so what's the point? Idealism and poor assumptions by the language designer. Anyone have any proof that a Java app is more reliable than a C# one?
breadwinner|2 years ago
More on checked vs unchecked exceptions here: https://forum.dlang.org/thread/hxhjcchsulqejwxywfbn@forum.dl...
jabiko|2 years ago
That bug should have been caught by tests, code reviews and good communication.
wvenable|2 years ago
I couldn't disagree more. Checked exceptions in Java have ruined a generation of programmers.
The truth is, under checked exceptions, to satisfy the compiler the function that you called would declare that it throws a SomeModuleException and the programmer who wrote that function would put all his code in try/catch block that catches all errors and rethrows a SomeModuleException with the real exception passed as the cause.
Checked exceptions just don't work.
__jem|2 years ago
h4x0rr|2 years ago
taeric|2 years ago
There is no magic language trick that can prevent you from having to rerun all tests for your software if you update a dependency. Pretty much period.
(I say this as someone that isn't really opposed to checked exceptions.)
nradov|2 years ago
sonicgear1|2 years ago
skissane|2 years ago
Not necessarily. If it started throwing a new RuntimeException, it wouldn’t have. There are also sneaky ways to throw checked exceptions without declaring them, for example using Lombok’s @SneakyThrows annotation
oh_sigh|2 years ago
29athrowaway|2 years ago
joiqj|2 years ago
bedobi|2 years ago
Functional error handling types are much simpler, safer and more powerful.
Simpler because they don't rely on dedicated syntax- they're just regular objects no different to any other object.
Safer because unlike exceptions, they force callers to handle all potential outcomes, but no more. (no risk of ignoring errors and no risk of catching a higher level of error than desired, ubiquitous bugs in exception based error handling)
Powerful because they support map, flatmap, applicative etc, making it easy to eg chain multiple computations together in desired ways, which is unwieldy and bug prone when using exceptions.
> What is wrong about dedicated syntax
It adds complexity to the language! It could be that, when learning Java, Kotlin and any other language, we learn that methods return what they say they do... and that's that. No weird dedicated syntax and magic, special treatment for returning anything other than the happy path, and the HUGE complexity that comes with it, eg the dedicated syntax itself and how it behaves, differences between checked and unchecked exceptions, hierarchies of exceptions etc etc.
> Exceptions are easier
But that's the point, they're not.
Exceptions based error handling is unnecessary, hugely complex, doesn't compose at all, obfuscates or straight up hides what can go wrong with any given call, so leads to countless trivially preventable bugs... I could go on. And after decades of use, there's still no consensus about what exceptions should be or how they should be used. Exceptions are a failed experiment and I have no doubt that in ten years, Java, Kotlin and many other languages will acknowledge as much and move away from it the same way Joda Time outcompeted and replaced the horrible Java date and time library.
kaba0|2 years ago
In my book, if anything, they are much much better! Unfortunately they don’t have a flawless implementation, but hopefully languages with first-class effects will change that.
misja111|2 years ago
I would also argue that checked exceptions are no more complex than Eithers, Try or Applicatives. Actually passing Eithers or Applicatives around everywhere can easily clutter your code as well, IMO it can be worse than checked Exceptions.
The_Colonel|2 years ago
Which is bad. In 99% of cases I have no specific error handling for the given problem. Just let the process crash or be handled by application server / framework.
Representing these kinds of error conditions in the code which I have no interest in handling is just noise.
spion|2 years ago
That said, not modelling them in the type system is a mistake. But the model has to be useful - knowing what functions can or cannot throw is useful, knowing what they throw, less so.
(They are safe because of try-finally / try-with-resources)
wvenable|2 years ago
That's what wrong with them. Callers, in almost all cases, do not know what to do exceptional outcomes. So you force programmers into a situation where they're dealing with things they shouldn't be dealing with.
unknown|2 years ago
[deleted]
asddubs|2 years ago
asddubs|2 years ago
_old_dude_|2 years ago
That's why Stream::map can not capture the checked exceptions properly.
josephcsible|2 years ago
nepthar|2 years ago
I'm sure I'd get used to it eventually, but I like that unchecked exceptions in Java are now an option!
Delk|2 years ago
If it's some random web backend, it's often fine to just let the error propagate as a 5xx. Many error cases wouldn't have a better solution anyway, and all that's breaking is a single page or resource load. (Of course on the frontend it might be nicer to show some kind of an error than just e.g. having frontend functionality silently fail.)
If it's a desktop application and you're crashing the entire application because wifi happened to drop or whenever there's anything your happy path didn't predict, that's going to be bad.
If it's some kind of an embedded thing and you're crashing an entire device because you didn't bother to handle cases that are outside of the happy path but entirely possible, I only hope it's not something important you're developing.
asddubs|2 years ago
ziml77|2 years ago
EspressoGPT|2 years ago
the_gipsy|2 years ago
raincole|2 years ago
Of course everyone like coding like this. No one likes to code error handling code.
Just like no one likes to code tests and documentations.
It turns out not every important thing is joyful.
clownvorld|2 years ago
https://www.artima.com/articles/the-trouble-with-checked-exc...
taftster|2 years ago
The fact that Java has introduced UncheckedIOException, in my opinion, shows how some people in the Java community have come to believe that checked exceptions were a mistake (understanding that lambda forced the issue). There's probably not too much to be easily done at this point, but consideration for changing checked exceptions in the JDK to extend RuntimeException sure would be interesting.
zeedude|2 years ago
https://github.com/manifold-systems/manifold/tree/master/man...
With an article having the same name as your post:
https://github.com/manifold-systems/manifold/blob/master/doc...
nnnnico|2 years ago
RGBCube|2 years ago
I honestly think the best error handling strategy is employed by Zig, then Rust. they're very explicit while not getting in the way, you always know what throws what and what doesn't.
Rust has a little issue though, which is that people can make their functions return `Result<T, Box<dyn Error>>` which makes handling the returned error difficult, Zig does not have any of that.
_old_dude_|2 years ago
But I don't think C#, Kotlin or Scala are less safe than Java even if they do not have the concept of checked exceptions.
tasubotadas|2 years ago
>Makes it impossible to call a function safely ?? catch(Exception e) anyone?
[1] https://literatejava.com/exceptions/checked-exceptions-javas...
rho4|2 years ago
wvenable|2 years ago
I have a desktop application with a single exception handler wrapping it's event loop. The handler display the message to the user and returns the to loop. It's rock solid -- nothing can crash it. The user can try to save their file to some network share that just disappeared and when that fails just save again somewhere else.
But there is no such thing a safe function to call. Whether you handle errors by meticulously passing them around everywhere or not makes little difference.
ars|2 years ago
Instead of the exception type being checked or unchecked, the throw should specify checked or unchecked.
So for example the first time the exception happens it can throw a checked exception for the caller to deal with.
If the caller doesn't deal with it it can simply throw its way all the way to the top without every single function needing to declare they handle it.
nnnnico|2 years ago
w10-1|2 years ago
This tool does remind us that checked exceptions in Java are a compile-time phenomenon only, so (non-compliant) compilers can be made to ignore them. Neat, but... helpful? It would certainly lock you into using the tool.
Instead, we need configurable policies for error handling, where the same code can be statically analyzed much more deeply (e.g., to include unchecked exceptions) or run more leniently (e.g., when exceptions are used only for flow control). Some of this might pertain to local declarations, and some might be policies of various scopes (per VM, per-package, or per call-chain), and would probably fold in assertions and fibers/virtual threads and some OS-sensitive behaviors. The goal would be to write the code once (with full disclosure, i.e., only check-able exceptions and assertions), but to reuse the same code under different policies.
Whether anyone wants to do the work of folding this into the VM as security privileges were is another question...
smrtinsert|2 years ago
theanonymousone|2 years ago
- It requires modifying compiler arguments and putting some file in the local classpath! That's really not Java-ic. Is it?
- It is not transparent in the code. You cannot infer by looking at the source code that something has changed.
Since some time ago I use the NoException library[0] in my Java projects which achieves the same goal but without the above-mentioned issues. It can also be used to mimic Scala's Try construct.
[0] https://github.com/robertvazan/noexception
dtech|2 years ago
As for alternatives, Try/Result and similar monads have decent adoption even in Java, but personally I quite like the Kotlin philosophy [1] to not have generic error containers and either use runtime exceptions for errors that cannot be reasonably handled by the caller and encapsulate failures in the return type if they can.
[1] https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/...
earthboundkid|2 years ago
phoe-krk|2 years ago
TIL!
galaxyLogic|2 years ago
What I don't like is the examples of having to use Maven or Gradle to install it. Why does that have to be so verbose, and something written in another language?
rogerkeays|2 years ago
[EDIT] I moved the command line stuff back to the top of the README. XML makes my eyes bleed too...
unknown|2 years ago
[deleted]
briffid|2 years ago
Hackbraten|2 years ago
As you correctly mentioned, if you leave the compile-time type of a variable unchanged, then assign a different object (one that belongs to a subclass that doesn’t throw the exception when you call its method) to that variable, and then call that same method, the compiler still forces you to catch. That’s the Liskov substitution.
dejj|2 years ago
https://projectlombok.org/features/SneakyThrows
throwaway2037|2 years ago
When I write code in C#, I always left wondering: Does this method throw an exception (ignoring null pointer and invalid arguments)? It bothers me. And, I write that as someone who really likes C# -- it's a great language for my needs.
And, yes, I can appreciate that many people don't like the friction associated with checked exceptions. It does add a lot of visual bloat! Serious question: What are the alternatives that _communicate sufficiently_ through an interface? Honestly, I struggle to think of a better alternative, so I just live with it.
Just like the bad old days of integer return values used to indicate error state (C-like languages), you need to check every single call -- there are no shortcuts, especially with I/O. For me, it is similar with Java and C# when writing I/O code: You need to catch and correctly handle every (checked-ish) exception.
rho4|2 years ago
Also, without IDE support such a plugin will never gain a lot of traction.
zeedude|2 years ago
https://github.com/manifold-systems/manifold/tree/master/man...
exabrial|2 years ago
I do just want to correct a tiny piece of the readme:
> a common practise is to rethrow it as a RuntimeException. The problem with this, ... is that the root cause of exceptions get hidden,
This is most definitely not true. If you wrap / re-throw as a RuntimeException you will absolutely get your original stack trace.
edpichler|2 years ago
code_runner|2 years ago
lucasyvas|2 years ago
watwut|2 years ago
dtech|2 years ago
code_runner|2 years ago
vbezhenar|2 years ago
That said, patching compiler is not something I would do.
What I usually do is add unchecked exception class for every checked exception I had to "handle". So I have UncheckedIOException from standard library (handy!), UncheckedSQLException and so on and so on.
Yes, it causes more code, but Java is not exactly known for brevity, so be it. At least that way is not hacky in any way and actually used by Java standard library itself, so I'd consider it "idiomatic".
rogerkeays|2 years ago
This is from my original solution to the problem: https://github.com/rogerkeays/jamaica-core/blob/0cc98b114998...
flerchin|2 years ago
jameslars|2 years ago
There was maybe a time Lombok made sense. It does not anymore. Death to Lombok.
alanfranz|2 years ago
I'd like something to soften some of them, probably in a configurable way, in some builtin interfaces btw. E.g. many IOExceptions should really be unchecked.
javajosh|2 years ago
Note: I will try it, because maybe I'm wrong.
rogerkeays|2 years ago
code_runner|2 years ago
Checked exceptions are far and away the worst part of java and I'm glad that no other language I've personally encountered have them!
On a more real note, I work at a shop with a fair amount of java now and checked exceptions are definitely my biggest complaint. I hope we adopt this, I'm sure we won't, but I'm glad to see a little movement on what I feel is the crusty status quo in the java world.
bottlepalm|2 years ago
Especially the higher the level the code is the more potential lower layers that can fail. It's just not scalable to write code up front to deal with every single case. And most programmers don't care about failure, or working around it, just success.
On the other hand we do expect the unexpected and wrap failure prone code in try/catch so that we can log exceptions and keep the app moving. Figure out later if the ROI is there from enough failures to write special code to try to prevent and/or recover from a particular exception.
It's pretty much the same as it is in the checked exception world just with more code - in Java people handle the exception, log it and/or rethrow, so what's the point? Idealism and poor assumptions by the language designer. Anyone have any proof that a Java app is more reliable than a C# one?
edpichler|2 years ago
ars|2 years ago
Vast majority of the time either the caller will fix it, or it simply does not need to be fixed at all it's simply passed all the way up to the top.
invalidname|2 years ago
_ea1k|2 years ago
The type-safe JSON feature in Manifold could be incredibly useful.
dgellow|2 years ago
_ZeD_|2 years ago
dtech|2 years ago
lesuorac|2 years ago
arein3|2 years ago
darklycan51|2 years ago
macpete42|2 years ago