<div dir="ltr"><div>> I've found that there are a lot of people out there who quietly think checked exceptions are ... pretty OK.</div><div><br></div><div>Count me in this camp. Checked exceptions are so much better than error return codes.</div><div><br></div><div>Changing everything to unchecked exceptions would be terrible. Step 1 of programming is to write code that works for the main case. Checked exceptions ensure that some of the corner cases must be dealt with, and if handled well, the code will be more robust.</div><div><br></div><div>For example, I wrote some code that tried to delete from the wrong part of the file system. Because I handled the IOException, the code was able to continue in the right part of the file system and the functionality wasn't broken. I can take care of the bug later instead of having to do so right away.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Nov 12, 2022 at 3:50 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<font size="4"><font face="monospace">I appreciate John's points
here. I don't necessarily agree with all of them (there's a
spectrum of opinions, and that's fine, though I find #3
especially compelling), but I think this illustrates something
about the exceptions debate that is easy to miss: the people who
hate checked exceptions are much noisier about it than those who
don't, and so they are likely to be fooled by confirmation bias
since all the other loud voices seem to agree with them. But
I've found that there are a lot of people out there who quietly
think checked exceptions are ... pretty OK. Maybe even a
majority. They just don't want to engage in a big debate,
they'd rather get their work done. <br>
<br>
<br>
<br>
</font></font><br>
<div>On 11/12/2022 11:16 AM, John Hendrikx
wrote:<br>
</div>
<blockquote type="cite">
<div>I very much disagree with this position, so I will make a
case for checked exceptions:</div>
<div><br>
</div>
<div>1) Without checked exceptions, using exceptions for
alternative outcomes as part of the contract of an API would no
longer be possible. This is because adding a new exception to
the API would no longer be a breaking change. Documentation is
not going to save you here. Effectively, exceptions would have
only two uses left (like in other languages): fatal JVM breaking
errors and to signal mistakes that could have been prevented by
the programmer. Using them to signal unpreventable errors would
be highly suspect and likely quickly be considered a bad
practice.</div>
<div><br>
</div>
<div><span>In other languages (but also in some Java API's that
use runtime exception to signal unpreventable errors) the
compiler cannot help you with these alternative outcomes as it
isn't even required to specify them as part of your API. It
helps you with the return value, but not for any other
outcomes. These other outcomes will now have to guessed,
gleaned from the documentation (if it is up to date), or by
doing manual code mining (of the called function and all the
functions it calls). Worse, these outcomes can change in
later releases without any warning as they're non-breaking
changes.</span><br>
</div>
<div><br>
</div>
<div>2) API's without checked exceptions will <span>necessarily
become more cluttered than their counterparts with checked
exceptions. They would have to return wrappers or unions or
special values to enforce proper use. API design like this
prevents easily deferring the handling of rare occurrences
higher up the call chain with standard idioms to keep the
current code path clean and to the point.</span></div>
<div><br>
</div>
<div><span>3) Removing checked exceptions now would break the
**design** of many current API's, making them dangerous to use
without the checks and balances that were present when they
were designed.</span><br>
</div>
<div><br>
</div>
<div><span>4) Earlier design decisions to exclude checked
exceptions from new idioms and API's were a mistake that
should be rectified not doubled down upon. A large part of the
momentum against checked exceptions comes from the clumsy way
that checked exceptions must be handled while using these new
features that were essentially </span><span>incompatible with
existing </span><span>Java. Even with the current status quo,
it is possible to design API's that do allow checked
exceptions in combination with functional programming, it is
just cumbersome to design these API's without a dedicated
union type (for exceptions). They either support only one
checked exception or some limited number. Their use is
however as transparent as API's that do not support checked
exceptions.</span><br>
</div>
<div><br>
</div>
<div>5) The fact that the value of checked exceptions is hard to
recognize or cumbersome for beginners or non-Java developers
should not have any bearing on language design.</div>
<div><br>
</div>
<div>Checked exceptions differentiate between the common
preventable programming errors and essential business logic. The
difference between a runtime exception (leaving out Error) and a
checked exception is that one can only occur in incorrect code,
while the other can occur even in correct code. One indicates a
preventable programming mistake and the other a missed path in
your logic. Throwing these on the same heap will effectively
reduce the usefulness of all exceptions to programming mistakes
(and fatal errors) only.</div>
<div><br>
</div>
<div>6) If anything, I think there should be way to promote
runtime exceptions to checked exceptions within certain
modules. This would allow API / library designers the option to
have the compiler check their code for missed documentation and
missing logic even for what externally would be a runtime
exception. This would be especially useful during initial
design and also later refactoring as the incredibly useful
compiler checks for checked exceptions could be extended to
proper use and propagation of runtime exceptions within that
module.</div>
<div><br>
</div>
<div>--John</div>
<div><br>
</div>
<div><br>
</div>
<div>------ Original Message ------</div>
<div>From "Remi Forax" <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>></div>
<div>To "Nathan Reynolds" <<a href="mailto:numeralnathan@gmail.com" target="_blank">numeralnathan@gmail.com</a>></div>
<div>Cc "amber-dev" <<a href="mailto:amber-dev@openjdk.org" target="_blank">amber-dev@openjdk.org</a>>;
"amber-spec-experts" <<a href="mailto:amber-spec-experts@openjdk.java.net" target="_blank">amber-spec-experts@openjdk.java.net</a>>;
"Ron Pressler" <<a href="mailto:ron.pressler@oracle.com" target="_blank">ron.pressler@oracle.com</a>></div>
<div>Date 12/11/2022 08:58:57</div>
<div>Subject Retiring Checked Exceptions Was: Throwing Functions</div>
<div><br>
</div>
<div id="m_2620927332475666945x9d362d73cbfa429">
<blockquote cite="http://839324466.44117145.1668239937777.JavaMail.zimbra@u-pem.fr" type="cite">
<div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<div>[promoted to amber-spec-experts]<br>
</div>
<div><br>
</div>
<div>I think we should tackle this problem at its core and
retire the notion of checked exceptions</div>
<div><br>
</div>
<div>The written are on the wall since quite some time, but
we have not yet acknowledge it.</div>
<div><br>
</div>
<div>Let's recap the issue and the clues pointing in that
direction.<br>
</div>
<div><br>
</div>
<div>I believe the first straw can be tracked back to the
inability of the type system to create a type variable
containing the union of exceptions when generics where
introduced in Java 5.<br>
</div>
<div>It's the reason why there is no ThrowableConsumer, as
an example, imagine that a stream can declare a checked
exception Stream<T, E> and a user call map() that
takes a ThrowableFunction,<br>
</div>
<div>we need a way to express that the resulting stream is
that combine the exceptions of the original stream and the
exceptions that may be raised by calling the function of
map.<br>
</div>
<div><br>
</div>
<div> Stream<T, E extends Exception> -->
map(ThrowableFunction<T, R, F extends Exception>)
--> Stream<R, E | F><br>
</div>
<div><br>
</div>
<div>Or perhaps from the beginning of Java, adding a checked
exception to a "throws" colors the function the same way
the keyword async or Rust lifetime type information color
a function [1]. Adding a checked exception to a function
is not a backward compatible change.<br>
</div>
<div><br>
</div>
<div>So we have some of idioms that beginners need to
internalize to try workaround checked exceptions,<br>
</div>
<div>- The oldest is i think,
Thread.currentThread().interrupt() which allows to silence
an InterruptedException at the price of continuing to
execute the code until the next blocking call</div>
<div>- UncheckedIOException and IOError that both wrap an
IOException into an unchecked exception allowing tunneling
of checked exceptions ; wrapping an IOException and
unbundle it later.<br>
</div>
<div>- Unsafe.rethrow (this one was retired)<br>
</div>
<div>- the unfamous rethrow using erasure to see a checked
exception as an unchecked exception<br>
</div>
<div> static <T extends Throwable> AssertionError
rethrow(Throwable cause) throws T {<br>
throw (T) cause;<br>
}<br>
- IntelliJ has changed the default try/catch snippet to
instead of calling printStackTrace() to throw a
RuntimeException wrapping the exception.<br>
</div>
<div> This simple change is i believe the best change to
Java in the recent years (perhaps toes to toes with
records), at least now the code of my students does not
print the stack trace and resume its course when an
exception occurs.<br>
</div>
<div> try {<br>
</div>
<div> ...<br>
</div>
<div> } catch(FooException e) {<br>
</div>
<div> throw new RuntimeException(e);<br>
</div>
<div> }</div>
<div><br>
</div>
<div>Also no language presented as potential successor of
Java, neither Scala nor Kotlin have checked exceptions,
because functions with checked exceptions do not compose.<br>
</div>
<div>If Java wants to be the next Java, we will have to drop
checked exceptions at some point.<br>
</div>
</div>
</blockquote>
<font face="arial, helvetica, sans-serif">
<div id="m_2620927332475666945x9d362d73cbfa429">I don't see the relevance of what
other languages are doing with their own agenda's. There is
no need to drop checked exceptions, they just need to be an
integral part of the whole. Removing them doesn't make Java
the next Java, it just makes it yet another language with
slightly different syntax that succumbed to a vocal minority
that values simplicity over safety.</div>
<br>
</font>
<blockquote cite="http://839324466.44117145.1668239937777.JavaMail.zimbra@u-pem.fr" type="cite">
<div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<div>The good news is that seeing all exceptions as
unchecked exceptions is a backward compatible change,
"throws" can still be supported for documentation purpose,
the compiler can emit a warning instead of an error if
there is no catch corresponding to a checked exception and
allow everyone to catch any exceptions in the code.<br>
</div>
</div>
</blockquote>
<font face="arial, helvetica, sans-serif"><br>
</font>
<blockquote cite="http://839324466.44117145.1668239937777.JavaMail.zimbra@u-pem.fr" type="cite">
<div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<div><span><br>
</span></div>
<div><br>
</div>
<div>I think we should recognize that the idea of checked
exceptions was a good idea on paper but not a good one in
practice and work to retire the concept of checked
exceptions from Java.</div>
<div><br>
</div>
<div>Rémi<br>
</div>
<div><br>
</div>
<div>[1]
<a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/" target="_blank">https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/</a><br>
</div>
<div><br>
</div>
<hr id="m_2620927332475666945zwchr">
<div>
<blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><b>From:
</b>"Nathan Reynolds" <a href="mailto:numeralnathan@gmail.com" target="_blank"><numeralnathan@gmail.com></a><br>
<b>To: </b>"amber-dev" <a href="mailto:amber-dev@openjdk.org" target="_blank"><amber-dev@openjdk.org></a><br>
<b>Sent: </b>Saturday, November 12, 2022 5:47:10 AM<br>
<b>Subject: </b>Throwing Functions<br>
</blockquote>
</div>
<div>
<blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt">
<div dir="ltr">
<div>I am sorry if I am very late to the discussion.
Consumer, Function, Predicate, and Supplier don't
allow for throwing checked exceptions. This feature
is needed in many cases. What about adding a
variant that allows for throwing checked
exceptions? For example, a ThrowableConsumer could
be defined as such...</div>
<br>
<div>public interface ThrowableConsumer<T, E
extends Throwable></div>
<div>{</div>
<div> void accept(T t) throws E;</div>
<div>}</div>
<br>
<div>A method that receives this as a parameter could
be defined as such...</div>
<br>
<div>public <E extends Throwable> void
process(ThrowableConsumer<T, E> consume)
throws E</div>
<div>{</div>
<div> ...<br>
</div>
<div>}</div>
<br>
<div>The compiler takes care of ensuring the checked
exception is dealt with in the caller to process().</div>
</div>
<br>
</blockquote>
</div>
</div>
</blockquote>
</div>
</blockquote>
<br>
</div>
</blockquote></div>