multi-catch vs. multiple type patterns in a single case label
Brian Goetz
brian.goetz at oracle.com
Fri Apr 8 21:25:42 UTC 2022
There's really three questions fused together here; one about union
types, one about the feasibility of pattern fusion, all wrapped up in
one about syntax.
Multi-catch was added to Java in Java 7, as part of "Project Coin"; the
mission of Coin was highly constrained. When extrapolating from the
syntax of multi-catch to an imagined syntax of OR patterns, there is a
subtle difference between:
case (IOException | TimeoutException) e: // parens added for effect
(Before continuing, what is the type of e?)
and
case (IOExcetion e) | (TimeoutException e): // parens added for effect
which is more of an OR of patterns.
Multi-catch did not add general purpose union types to the language; it
focused them on one little corner. (We can argue over whether this was
a clever pragmatic compromise, or whether we merely created a lot of
incremental language complexity for minor gain.) It is possible it
might make sense to add it in another corner too, but we're wary of such
moves, because such types invariably escape into inference and produce
weird, non-denotable types elsewhere. (See the travails over how to
sanitize capture types with `var`.) So just copying what multi-catch
does is not an obvious slam-dunk.
OR patterns are a more powerful mechanism, and one we'd like to
consider, but they are complicated too. In the second example, `e` has
*two* declaration sites, and we still probably end up inferring a union
type for it, or maybe we infer the least-upper-bound (which is often
Object). So this is also not an obvious slam dunk either.
So the short answer is that just because there is a way to express
something somewhere, doesn't mean that carries over to other similar
things elsewhere. Even if the syntax would be obvious.
On 4/8/2022 10:03 AM, Tobias Gierke wrote:
> Hello,
>
> Having read through JEP-420, I wonder why
>
> try {
> .... do stuff ....
> } catch( IOException | IllegalStateException e) {
> System.out.println("Something went wrong: "+e);
> }
>
> is valid but
>
> Exception x = ....
> switch(x) {
> case IOException | TimeoutException e ->
> System.out.println("Something went wrong: "+e);
> }
>
> is not. I get that something like
>
> Exception x = ....
> switch(x) {
> case IOException a, IllegalStateException b -> .....
> }
>
> would leave one of the variables undefined but why can't I bind
> multiple type patterns to the same variable, have the compiler infer a
> common super-type and use that to check the switch branch ?
>
> Regards,
> Tobias
>
More information about the discuss
mailing list