5 ms·
> You are right, but you still have to catch the checked > IOException. Rather than which alternative? There are tonnes of IO errors that can occur and are ca
by bArray 7y ago
> You are right, but you still have to catch the checked
> IOException.
Rather than which alternative? There are tonnes of IO errors that can occur and are captured in Java that you may not ever even consider. IO is exceptionally tough and programmers should be aware that there could be 1 of a possible million reasons for failure, even if they don't care exactly why.
It's not a massive ask either:
try{
/* Perform some IO that 99.999999% of the time */
}catch(Exception e){
/* Something went wrong and we don't know the state of the disk */
}
Personally I believe applications should have their own wrapper around IO and handle it accordingly. I.e. not caring, re-trying, show-stopper, etc, etc.
A lot of code I've written will have the following if I really don't care if it works or not:
try{
/* IO code */
}catch(Exception e){
/* Do nothing */ // <-- Let others know that this was on purpose
}
- nostrademons 7y agoFor a lot of scripts you want the program to crash with a stack trace if you get an IOException, which is the default behavior if it's uncaught. The user is the developer, and if there's an error the developer fixes it by munging something on their filesystem. Java was designed for "production" software, which in the late 90s and early 00s meant software that ran for long periods of time as a server, servicing thousands of mission-critical customers. Crashing was not acceptable behavior for that. But now a lot of production software often requires a lot of ancillary one-off tasks that are just done by the developers - testing, data-munging, exploratory code, migrations, demos, etc. That's a very different environment from where you code to spec, the spec never changes, and once the software is done it's supposed to run for years without crashing.
- erik_seaberg 7y agoEarly Java was designed for set-top boxes and then web browsers. Large-scale servers came later; in fact a lot of libraries still don't support the async futures that were officially added five years ago.
- paulddraper 7y ago99% of the time I want to do the same thing for IOException as I would for NoSuchElementException or a DOMException. That said, even if typed checked exception handling is important...it quickly becomes untenable. Thing thing = create(); try { ... } finally { cleanup(thing); } You might try to abstract this withThing(thing -> ...) But what if "..." potentially throws IOException? What if it potentially throws IOException or AWTException? You have to give up all your exception type safety to make an abstraction like withThing. It's just not composable.
- barrkel 7y agointerface ThrowingConsumer<T, E extends Exception> { void accept(T value) throws E; } // ... <E extends Exception> void withThing(ThrowingConsumer<Thing,E> callback) throws E { ... } The problems are that (a) you need to add an extra type parameter for exceptions all over the place, (b) exception unification (sum type) doesn't work generically - you can say E1 | E2 in a catch block but it's not a real type, and (c) it composes poorly with existing libraries that expect Consumer<T> throughout. For one level deep callbacks (for resource handling and the like) it works reasonably well though.
- paulddraper 7y ago(b) is what I had in mind as the problem.
- krab 7y agoYou can always opt out of the typed checked exceptions. try { ... } except (IOException|NoSuchElementException e) { throw new RuntimeException(e); } If you decide you don't want checked exceptions in your code, wrapping the exceptions at the boundaries is not a huge deal.
- paulddraper 7y agoOr switch to a language that does that for you, like Scala or Kotlin.