Retiring Checked Exceptions Was: Throwing Functions
Remi Forax
forax at univ-mlv.fr
Tue Nov 15 15:40:15 UTC 2022
> From: "John Hendrikx" <hjohn at xs4all.nl>
> To: "Stephen Colebourne" <scolebourne at joda.org>, "Amber dev"
> <amber-dev at openjdk.java.net>
> Sent: Tuesday, November 15, 2022 1:15:27 PM
> Subject: Re[2]: Retiring Checked Exceptions Was: Throwing Functions
> I just wanted to add an observation here.
> I now have seen several ideas here that seem to point to a solution which just
> allows lambda's to throw checked exceptions (with a warning or automatically
> converted to unchecked), but what I find odd is that this wouldn't solve
> anything at all. These functions are almost by definition not used or called
> immediately, and so the actual checked exception can occur in a totally
> unrelated part of the code that may not be prepared to handle it: this
> unrelated code would not be declaring any exceptions and the compiler would
> give no warnings or errors, but a checked exception can now pop up there
> uninvited.
> The simplest example are streams. When you write:
> Stream<URI> createStream() {
> return List.of("file:/xyz").stream().map(URI::new); // throws URISyntaxException
> }
> There is no need to declare anything, and any warnings or errors would make no
> sense. Allowing the above method to declare "URISyntaxException" is just plain
> incorrect, leaving you to write a catch block (or rethrow) to deal with
> something that can't happen.
> Then in a completely unrelated part of the code you may use this stream:
> stream.toList();
> There is no sign of the lambda, toList() doesn't declare checked exceptions, but
> this can now throw URISyntaxException.
> IMHO solutions that just allow you to pretend the checked exception doesn't
> exist are going to just muddy the waters further, and don't really solve the
> problem at all. They just make it easier to hide the problem, and in doing so,
> create new problems. I think it is possible to do better and find a solution
> that doesn't come with a new set of problems.
You have to compare with what is done currently, when you write this in your IDE
Stream<URI> createStream() {
return List.of("file:/xyz").stream().map(URI::new); // throws URISyntaxException
}
the IDE will happily transform the code to
Stream<URI> createStream() {
return List.of("file:/xyz").stream().map(s -> {
try {
return new URI(s);
} catch(URISyntaxException e) {
throw new RuntimeException(e);
}
});
}
which is in my opinion worst than considering URISyntaxException as unchecked, because here the type of the exception is lost by wrapping it into a runtime exception.
So yes, the proposed solution is far from ideal, but i believe a warning is a better answer than wrapping all checked exceptions into unchecked ones.
> --John
Rémi
> ------ Original Message ------
> From "Stephen Colebourne" < [ mailto:scolebourne at joda.org | scolebourne at joda.org
> ] >
> To "Amber dev" < [ mailto:amber-dev at openjdk.java.net |
> amber-dev at openjdk.java.net ] >
> Date 15/11/2022 10:41:15
> Subject Re: Retiring Checked Exceptions Was: Throwing Functions
>> I outlined simple, practical approach to this when lambdas were first added to
>> Java [1]. Much of the blog post above is no longer especially interesting, but
>> the basic "lone throws" concept still is. The key part is repeated in these
>> three bullet points:
>> * Any method may have a throws keyword without specifying the types that are
>> thrown ("lone-throws"). This indicates that any exception, checked or unchecked
>> may be thrown. Once thrown in this manner, any checked exception flows up the
>> stack in an unchecked manner.
>> * Any catch clause may have a throws keyword after the catch. This indicates
>> that any exception may be caught, even if the exception isn't known to be
>> thrown by the try block.
>> * All closures are implicitly declared with lone throws. Thus, all closures can
>> throw checked and unchecked exceptions without declaring the checked ones.
>> I suspect it is too late for the last bullet point to be adopted, but the first
>> two would IMO still be hugely beneficial to Java. The point here is not to
>> reject the idea of checked exceptions, but to provide a convenient way to
>> convert/handle them when they are not what you want.
>> Various alternative mechanisms are in use today:
>> * additional functional interfaces such as ThrowableFunction
>> * utilities like Unchecked.wrap(ThrowableSupplier) which convert checked to
>> unchecked
>> * hacks like "sneaky throw"
>> My argument is that there is a very clear use case in the global corpus of Java
>> code for a mechanism to convert/handle checked exceptions more like unchecked.
>> And that this would be a good language feature, given that it can be done
>> without threatening those who appreciate checked exceptions.
>> Stephen
>> [1] [
>> https://blog.joda.org/2010/06/exception-transparency-and-lone-throws_9915.html?m=1
>> |
>> https://blog.joda.org/2010/06/exception-transparency-and-lone-throws_9915.html?m=1
>> ]
>> On Mon, 14 Nov 2022, 23:09 Archie Cobbs, < [ mailto:archie.cobbs at gmail.com |
>> archie.cobbs at gmail.com ] > wrote:
>>> On Mon, Nov 14, 2022 at 4:52 PM < [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr
>>> ] > wrote:
>>>> I'm proposing to demote checked exceptions to make them second class citizen
>>>> because this practically what they are.
>>>> The problem is that the status quo is pushing people to use runtime exceptions
>>>> instead of exceptions because checked exception do not compose well, exactly
>>>> what we both do not want.
>>> I totally agree that the lack of composibility (composibleness?) is a problem.
>>> But I don't agree that ALL of the blame for that problem rests on checked
>>> exceptions. After all, checked exceptions have been around a lot longer than
>>> lambdas.
>>>> What if checked exceptions work like unchecked casts ?
>>> This sounds like a much more promising direction to go in.
>>> All we want is a simple way to tell the compiler "I know this lambda can throw a
>>> checked exception, just pass it through instead of making this impossible to
>>> compile".
>>> E.g. something like this??
>>> public <T> void execute( @PassThroughCheckedExceptions Supplier<T> getter) {
>>> return getter.get();
>>> }
>>> public InputStream openFile(File file) throws IOException {
>>> this.execute(FileInputStream::new);
>>> }
>>> -Archie
>>> --
>>> Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20221115/26439796/attachment-0001.htm>
More information about the amber-dev
mailing list