Or maybe I just want to defer the error management to a higher level. Again busywork declaring exceptions.
I'd also disagree that adding a throws to the signature is much boilerplate at all. Especially in the ages of IDE's
try { //your code } catch (Exception e) { throw new RuntimeException(e); }
around it and you'll be fine.
The thing about Java is that the code lasts for a really long time because when it fails, it does so usually with an exception that points to the problem. When promises hang in NodeJS or memory corruption happens in C, it's much more annoying to track down problems.
If you can get your team to commit to a "let it crash" policy, though, then it's pretty doable.
Better to check if it’s a runtime exception and throw it again without wrapping it. Only wrap if it’s not a runtime exception. Also you should check if the thread was interrupted and, if so, set the interrupt flag again.
The worst part of this is having that dance littered throughout all your code.
private static <T extends Throwable> T sneakyThrow(Throwable ex) throws T {
throw (T) ex;
}
Due to generic type erasure, the entire throw clause gets erased so it looks like this method doesn't throw anything.I mean, why are you writing a kleenex program in Java? Do you not want to declare a return type for your functions either? Java's checked exceptions are just a way to return multiple types from your methods: a success value and a failure values.
Why should I wrap simplest code with boilerplate? OK, maybe too late, since I need to write several lines of boilerplate to just say hello world. People argue that it's just a template that wraps the program. OK, but now it's something more fine-grained: every function must be wrapped.
The way I see it, simple code must be simple. If you want to do complex things, the language should allow you to do it some way. But not at the expense of everyday tasks. It's an elemental usability consideration.
I mean, why are you writing a kleenex program in Java?
See? The mindset again. That question I can't understand. Actually I find it annoying as in "what kind of language is Java that you thing Kleenex functions are not allowed? does it thinks it's too good for my crappy functions?"
Do you not want to declare a return type for your functions either?
If there isn't a return value, I don't.
Java's checked exceptions are just a way to return multiple types from your methods: a success value and a failure values.
Why do you need checked exceptions, as opposed to regular unchecked, typed exceptions?
As you already mentioned, that ship has sailed the second you decided to use Java. Every function already has to be wrapped in `class`, which is obnoxious.
> See? The mindset again. That question I can't understand. Actually I find it annoying as in "what kind of language is Java that you thing Kleenex functions are not allowed? does it thinks it's too good for my crappy functions?"
My point wasn't celebrating boilerplate. It's about having a statically typed language. If it's too much to either add `throws Exception` to your function signature or to write a try {} catch {} block, then it must certainly already be too much to write `class MyClass { void myMethod() }`, no?
> If there isn't a return value, I don't.
You still have to write `void`, don't you? And checked exceptions are supposed to be something you want to force on callers of your code- like a return value. You don't want to return anything? Then return `void` and don't throw any checked exceptions.
> Why do you need checked exceptions, as opposed to regular unchecked, typed exceptions?
Because it's part of your API. If you write:
`int fooMethod(int input) {...}`
Then you are saying "If you call `fooMethod` with an int you will get an int." If you always throw an exception on input == 3, then your API is now lying. You should either return a type that encodes the possibility of not being an int OR throw a (checked) InputWasThreeException, to be honest to your caller.
Java is a poor language. Ideally there would be an ergonomic way to use a Result/Try type a la Rust and Scala. If such a thing existed, I would stop advocating for checked exceptions immediately.
On that note: would it improve things, compared to checked exceptions that cause compile warnings if not handled?
I'm currently dealing with similar problem on the C++ side - a codebase that's using a lot of tl::expected<> and "functional interface" instead of exceptions. And the more I work with it, the more I realize this introduces a lot more of boilerplate/book keeping to achieve the same goal exceptions would, with little to no benefit - except the possibility of error being visible in function signature. Which wouldn't be a problem for exceptions if "throws" in C++ wasn't broken.
Rust, if you are not familiar, has a special operator that let's you call a function that returns Result and automatically unwrap it and return early if it's an Error rather than Success. It will even automatically CONVERT the error for you if you've defined the proper trait implementation to convert the one error type into the other.
So, in Rust the boilerplate happens ahead of time (implementing the conversion trait), outside of your function's internal logic. In your function you just write:
fn foo(): Result<String, Error> {
let f = something_that_can_faile()?;
uses_the_success_value(f)
}
No try{}catch{}, no match statements, nothing. Just a question mark.Swift also strikes a nice compromise, IMO. It just has a throws tag like C++, except it actually works.
I never considered a warning-level check for Java's checked exceptions. That sounds like a nice idea at first blush.
The simple code must be simple, but not simpler than that. For exploratory code it's fine to ignore the failure paths; for production code, it isn't. Java's checked exceptions force you to operate in the "production code" mode, so the language isn't super-convenient for prototyping. I'd personally like all exceptions to be checked, but with "checked exceptions as warnings" mode by default - with an understanding that production code will be built with "warnings = errors" switch.
> If there isn't a return value, I don't.
What if there isn't a return value in the success case, but there is one in case of failure (i.e. the error)?
> Why do you need checked exceptions, as opposed to regular unchecked, typed exceptions?
You don't need, but you probably want them. Unchecked exceptions are invisible in the method's signature; to get a list of exceptions you need to handle, you'd have to dig through implementations of everything downstream of your method.
There's a trend across different languages to use algebraic data types (Result, Expected, etc.) to allow returning a valid result XOR an error, which by design make you deal with a possible error if you want to get the result. Exceptions are essentially the same thing, except with less boilerplate (in C++/Java-style language), but you need checked ones to actually force the programmer to deal with failure modes.
Is the language "forcing" you when someone writes a function that returns a String? What if I wanted it to be an Int?
Edit2: hey TeMPOraL, I don't care too much about that, it's the feeling of being in a community where someone thinks this is an acceptable behaviour.
I've been writing here for very long. But this is getting ridiculous. Anything that is minimally controversial gets downvoted. And the thing is that I am already censoring myself a lot.
But it matters for me, the programmer using modules written by other co-workers and third party libraries, that I'm made aware of what can fail and at what point, when I'm using these modules/libraries. It also matters to me that my tools (e.g. the compiler) force me to handle these cases correctly, or at least warn me when I'm not - lest I ship broken code through carelessness or ignorance.
Quality Sun's API design is a different issue. This is about giving people tools to express and enforce error handling semantics in software they design.
EDIT:
> Edit: OK, someone is downvoting because opinions. No more comments by me.
It's good to not be attached to imaginary Internet points. They come and go and ultimately don't matter much. And FWIW, bad downvotes often get countered, and the score of a given comment settles to something reasonable over time.
Don't want to? Throw it on up the stack, but do so in the knowledge that your program will fall over at the first problem.
And even that is better than carrying on with (for example) a null that then trips up some random bit of code later.
Use Groovy. Seriously, you can code it up with zero boilerplate, use the REPL, notebooks, etc to get your idea into shape, all with 100% interop with your Java libraries.
When you are done, if parts of it should graduate to "real code", you can pretty easily port it over or keep parts of it in Groovy and just take the elements over that need to be Java for robustness, etc.
This is actually my standard workflow in development now.