9 ms·
Still nothing to handle checked exceptions in streams properly... sigh.
by crooked-v 8y ago
Still nothing to handle checked exceptions in streams properly... sigh.
- paulddraper 8y agoI share the conclusion of the other statically typed JVM languages (Scala, Kotlin): checked exceptions are bad.
- vbezhenar 8y agoIf they are officially bad, remove them from the language. It's a backwards-compatible change. Currently we are in a weird situation, when standard library does not work well with each other. It's like making iPhone without USB-C cable and Macbook without USB-A port.
- dragonwriter 8y ago> It's like making iPhone without USB-C cable and Macbook without USB-B port. Was there ever a MacBook with USB-B?
- paulddraper 8y ago> If they are officially bad, remove them from the language java.util.Date is bad, but it's not getting removed. java.net.URLEncoder is bad, but it's not getting removed.
- l1ambda 8y agoYes. One can workaround it with the throw-as-unchecked pattern: https://stackoverflow.com/questions/14038649/java-sneakythrow-of-exceptions-type-erasure https://stackoverflow.com/questions/14038649/java-sneakythro...
- joostdevries 8y agoI find checked exceptions interesting. They happen to be the only example of an effect system in a mainstream language. Anders Hejlsberg formulated the main argument against them here [1] Basically the problem is that checked exceptions are infectious and intermediary code needs to annotate all the exceptions of code that it calls. Which is a chore. Lucas Rytz states in his PhD thesis [2] that the problem is not wich checked exceptions themselves, but that in the java implementation 'not mentioning an exception means if won't happen'. He proposes a system where the default is 'any exception' and being able to turn it off with a compiler flag. And states that the developer experience of that would be much better. This may become possible in Dotty Scala using the effect system based on implicit functions. But that's in 'proposed' status. [1]https://www.artima.com/intv/handcuffs.html https://www.artima.com/intv/handcuffs.html [2]https://lrytz.github.io/pubsTalks/ https://lrytz.github.io/pubsTalks/ the link to his thesis doesn't work anymore. I cherry pick some of it in my talk for a Scala meetup in Utrecht https://www.slideshare.net/yoozd/effect-systems-in-scala-beyond-flatmap https://www.slideshare.net/yoozd/effect-systems-in-scala-bey...
- vbezhenar 8y agoI wonder why they didn't use generic exception type in their java.util.function classes. That would propagate checked exceptions statically. Something like @FunctionalInterface interface Function<T, R, E extends Throwable> { R apply(T t) throws E; }
- swsieber 8y agoAh, that's because java generics don't work with exceptions.
- vbezhenar 8y agoWhat do you mean? They do work with exceptions.
- swsieber 8y agoAh, my mistake. I was thinking of generice type arguments for exception subclasses: https://www.mscharhag.com/java/java-exceptions-and-generic-types https://www.mscharhag.com/java/java-exceptions-and-generic-t... That also includes generic catch clauses and inner exception types of classes with type parameters.
- Viliam1234 8y agoIn Java, the concept of exceptions is incompatible with the concept of parametrized types. During compilation, type parameters are erased. "T" becomes "Object"; "T extends Something" becomes "Something"; assignment becomes type conversion. But at the end it works correctly. If you try to make something that wouldn't survive the type parameter erasure -- such as having two methods with the same name, one of which accepts "List<String>" and another accepts "List<Integer>" as their input -- it will be a compile-time error, because you can't have two methods with the same name and the same parameter "List". But imagine that you have a type "MyException" extending RuntimeException, and your code has "catch (MyException)". After compilation, this would become "catch (RuntimeException)", which is wrong, because it would also catch other RuntimeExceptions, and it is not supposed to. But if you make this construction a compile-time error, then... the whole thing becomes useless, because what's the point of having an exception type you cannot catch.
- ars 8y agoOr in FunctionalInterface, or in anonymous functions. Makes HashMap computeIfAbsent much less useful than it should be. It's impossible to use a function in there that throws a checked exception (all I want is for the exception to propagate out of computeIfAbsent for the parent method to deal with). Best option I've found is to wrap it in an unchecked exception, then unwrap it in the parent method, which is just .... yuck.
- vbezhenar 8y agoAnother option is to fool the compiler. So-called sneaky throws. Something like public static void main(String[] args) { try { sneakyThrow(new IOException("io")); Test.<IOException>emulateThrows(); } catch (IOException e) { e.printStackTrace(); } } static void sneakyThrow(Throwable e) { Test.<RuntimeException>sneakyThrow2(e); } private static <E extends Throwable> void sneakyThrow2(Throwable e) throws E { @SuppressWarnings("unchecked") E e1 = (E) e; throw e1; } static <E extends Exception> void emulateThrows() throws E { }
- ars 8y agoThis only works if I'm throwing the exceptions myself, but not if I'm using a library function (like a rowMapper for example).
- vbezhenar 8y agoYou can write wrapper which takes function that can throw anything and returns regular java.util.function.Function. Here's example: https://github.com/rainerhahnekamp/sneakythrow/blob/master/src/main/java/com/rainerhahnekamp/sneakythrow/Sneaky.java https://github.com/rainerhahnekamp/sneakythrow/blob/master/s...
- benjiweber 8y agoFairly straightforward to handle yourself e.g. https://github.com/unruly/control/blob/master/src/test/java/examples/ExceptionsInStreamsHandling.java https://github.com/unruly/control/blob/master/src/test/java/...
- brown9-2 8y agoif you have to do this in every step of the Stream then it seems like a failed design.
- hyperpape 8y agoThis isn’t something where I remember the details, but the language designers decided there was not a good solution. There are some links from Brian Goetz in the comments/answers: https://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java-8-streams https://stackoverflow.com/questions/27644361/how-can-i-throw....
- spricket 8y agoNot in base java, but some libraries essentially fix this. Vavr https://www.baeldung.com/exceptions-using-vavr https://www.baeldung.com/exceptions-using-vavr But my favorite is abusing the language using Lombok SneakyThrows. It just feels dirty using it. In a good way.
- riku_iki 8y agoYou should return some ResultOrError<Result, Error> value instead of throwing Exception..
- Freak_NL 8y agoThat's what languages like Rust do with a return return type that is part of the core language. Sometimes I wish Java had one too to complement Optional. I wonder what the argument against that is? Too much confusion with the existing Exception system?
- lmm 8y agoJava managed to break the Optional type badly enough that it can't be used for its intended purpose (it can't contain null which would be great if the rest of the language couldn't contain null either, but as it stands it's not practical to port existing Java code to use Optional), so I wouldn't trust them to implement a working result type. Working with result types is really cumbersome in languages that don't have HKT (Rust hacks around it with a special-purpose language feature), and even more so in languages that also don't have pattern-matching. So I'm not sure how much use it would be in practice. But yeah it's the right way to solve the problem.