Retiring Checked Exceptions Was: Throwing Functions

Brian Goetz brian.goetz at oracle.com
Sat Nov 12 15:44:32 UTC 2022


Counter-proposal: let's just retire the endless stream of "let's just 
get rid of checked exceptions" proposals instead.

This is all well-traveled ground, and has all been brought up before 
(including by you several times.)  I get how attractive it is to "just" 
declare checked exceptions a mistake.  But even if it was, we know that 
trying to "fix" the "mistakes" of the past often only makes things worse.

There is interesting research going on in the Scala community and 
elsewhere about better treatment of effects; some of this may bear fruit 
that might be a better approach than the "just uncheck them all."  In 
any case, I'm not interested in reopening this discussion at this time; 
we have plenty else on the priority list.

Verdict: Motion Denied.  Leave is granted to refile your motion in 2025.


On 11/12/2022 2:58 AM, Remi Forax wrote:
> [promoted to amber-spec-experts]
>
> I think we should tackle this problem at its core and retire the 
> notion of checked exceptions
>
> The written are on the wall since quite some time, but we have not yet 
> acknowledge it.
>
> Let's recap the issue and the clues pointing in that direction.
>
> 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.
> 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,
> 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.
>
>   Stream<T, E extends Exception>  --> map(ThrowableFunction<T, R, F 
> extends Exception>) -->  Stream<R, E | F>
>
> 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.
>
> So we have some of idioms that beginners need to internalize to try 
> workaround checked exceptions,
> - 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
> - UncheckedIOException and IOError that both wrap an IOException into 
> an unchecked exception allowing tunneling of checked exceptions ; 
> wrapping an IOException and unbundle it later.
> - Unsafe.rethrow (this one was retired)
> - the unfamous rethrow using erasure to see a checked exception as an 
> unchecked exception
>    static <T extends Throwable> AssertionError rethrow(Throwable 
> cause) throws T {
>       throw (T) cause;
>    }
> - IntelliJ has changed the default try/catch snippet to instead of 
> calling printStackTrace() to throw a RuntimeException wrapping the 
> exception.
>   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.
>     try {
>      ...
>     } catch(FooException e) {
>       throw new RuntimeException(e);
>     }
>
> Also no language presented as potential successor of Java, neither 
> Scala nor Kotlin have checked exceptions, because functions with 
> checked exceptions do not compose.
> If Java wants to be the next Java, we will have to drop checked 
> exceptions at some point.
>
> 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.
>
> 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.
>
> Rémi
>
> [1] 
> https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
>
> ------------------------------------------------------------------------
>
>     *From: *"Nathan Reynolds" <numeralnathan at gmail.com>
>     *To: *"amber-dev" <amber-dev at openjdk.org>
>     *Sent: *Saturday, November 12, 2022 5:47:10 AM
>     *Subject: *Throwing Functions
>
>     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...
>
>     public interface ThrowableConsumer<T, E extends Throwable>
>     {
>        void accept(T t) throws E;
>     }
>
>     A method that receives this as a parameter could be defined as such...
>
>     public <E extends Throwable> void process(ThrowableConsumer<T, E>
>     consume) throws E
>     {
>        ...
>     }
>
>     The compiler takes care of ensuring the checked exception is dealt
>     with in the caller to process().
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20221112/ca14d37b/attachment-0001.htm>


More information about the amber-dev mailing list