Hello,
On 18/04/2022 5:43 am,
some-java-user-99206970363698485...@vodafonemail.de wrote:
Hello,
are there any plans to improve exception handling in combination with `finally`
blocks?
I'm not aware of anything, nor what that anything could realistically
be. You make only one suggestion that has a little merit.
Currently, when a `finally` block does not complete normally, the original
exception is
silently discarded (as described in the JLS). This behavior is error-prone, not
obvious
at all, and has been criticized in the past a lot. An example for this is
https://stackoverflow.com/q/48088
and the linked posts there.
The behaviour of try/catch/finally is not "obvious at all", you have to
read what it means and when you do that you clearly see what happens
regarding exceptions.
While javac warns you about this issue when using `-Xlint:finally`, it is only
a warning
and not even enabled by default.
Are there any plans to forbid usage of `break`, `continue`, `yield` and
`return` in
`finally` blocks?
Why would we do that? What would that gain?
Switch expressions have already set a precedent for this by not allowing to
leave the
switch expression by something other than a `throw` or `yield` statement,
trying to use
for example a `return` statement causes a compilation error.
That is because it is an _expression_ - expressions have to have
different language rules to statements. There is no connection to a
finally block.
Similarly for `throw` and any implicitly thrown exceptions, is there a plan to
at least
add the original exception as suppressed one to the newly thrown?
That suggestion is not completely without merit, but nor is it a
"slam-dunk" obvious thing to do. The semantic implications of the
exceptions matter, and semantics come from the programmers intent.
There's no reasonable way to automagically determine that when an
exception is created that another exception (that led to the finally
block) should be inserted as a "suppressed exception". That would
actually be completely wrong to do in many circumstances you would
instead need to act when the exception would terminate the finally block
and then add the original exception as the "suppressed" exception. But
really the programmer is in the best position to decide how exceptions
need to be handled.
Of course one could argue that the same applies to `catch` clauses whose body
accidentally
causes an exception which discards the caught one. However the main difference
is that
Yes exactly the same.
there, only a specific exception type is caught (and discarded), whereas for
`finally`
exceptions of _any_ type are discarded. It could also be argued that adding
suppressed
We have multi-catch now so that argument is somewhat weaker.
exceptions decreases performance or causes memory leaks, but one the other hand
this behavior was explicitly included try-with-resources statements, most
likely because the
value this adds was considered more important than any performance issues this
might cause.
try-with-resources added support for suppressed exceptions because the
automatic closing of the resource could throw an exception, and that had
to be factored in to the whole mechanism.
Also, it is important to keep in mind that this affects _all_ Throwable types,
including
VM errors which you really should not catch, and which due to a `finally` block
might
silently be discarded. Most, if not all, code in which a `finally` does not
complete
normally does not seem to consider this.
That is true. But for me a finally block is intended to be quite small
and succint and should be written from the perspective of "an unexpected
exception has occurred, what it is it critical for me to do before
leaving the current scope".
This is also not a theoretical problem; this issue exists in multiple open
source projects,
potentially even in the JDK itself.
Often the code can be rewritten by either moving the complete code or parts of
it
outside of the `finally` block, or by introducing a local variable to hold the
result and
to return that after the `finally` block.
What do you think about this topic?
I think there is no clear and obvious solution that the language can put
in place here.
Just my personal 2c.
Cheers,
David
Is backward compatibility a concern? If so, can you provide an example where
using such
a pattern provides any notable advantages which justify the potential loss of
thrown
VM errors or exceptions.
Kind regards