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" <[email protected]>
*To: *"amber-dev" <[email protected]>
*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().