Retiring Checked Exceptions Was: Throwing Functions
Kevin Bourrillion
kevinb at google.com
Tue Nov 15 16:21:40 UTC 2022
I agree with Brian that this discussion belongs somewhere other than
amber-dev.
It would be cool to see this thread die down. :-)
On Tue, Nov 15, 2022 at 7:49 AM Remi Forax <forax at univ-mlv.fr> wrote:
>
>
> ------------------------------
>
> *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" <scolebourne at joda.org>
> To "Amber dev" <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
>
> On Mon, 14 Nov 2022, 23:09 Archie Cobbs, <archie.cobbs at gmail.com> wrote:
>
>> On Mon, Nov 14, 2022 at 4:52 PM <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
>>
>
>
--
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20221115/d5dc66f7/attachment.htm>
More information about the amber-dev
mailing list