<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>