JEP 305 - Pattern Matching for instanceof (Preview)
Brian Goetz
brian.goetz at oracle.com
Sat Nov 23 19:43:19 UTC 2019
> 1. Can I write `obj instanceof String obj` and shadow the original
> `obj` variable with the new one?
>
> It would be nice if I could, because one of my main concern
> with the lack of "auto-cast", is that I have to give another name
> to the same thing, which usually leads to lame things like
> `o` and `other`.
No. It has been discussed, but so far, we are sticking with the
original rules about shadowing. We might consider relaxing it in the
future, but have ruled out doing so for now.
While I understand the attraction of flow typing, flow typing is in fact
a weaker mechanism than pattern matching (though that's not obvious
because we're starting with the weakest form of patterns, type
patterns). Bundling a tiny amount of flow typing with pattern matching
is not likely to make the flow-typers happy, and will also serve to
confuse people about what pattern matching is. But when we get farther
down the road with pattern matching, we may review this decision.
> 2. Is the newly declared variable final?
>
> I personally would prefer if it would be final, because then
> that is one less thing to worry about.
Pattern variables are final, yes.
> 3. Is it legal to do this kind of declaration even if the effective
> scope of that variable is nothing?
>
> For example, `if (obj instanceof String s || myCondition)`.
> As both path is reachable without `obj` being an instance of `String`.
Yes, just as it is legal to write:
void m() {
String s = "";
}
We don't go out of our way to forbid declare-and-then-don't-use. Note
that there are still places where you might want to use `s` in the above:
if ((obj instanceof String s && s.length() > 3) || myCondition) { ... }
even if you don't use it in the body of the if.
> 4. What is the limit for the compiler to figure out the scope of the variable?
>
> I was mildly surpised to see that `if (!(obj instanceof String s))`
> works on the else path.
The intuitive rule is "the binding is in scope wherever it would be
definitely assigned, and not in scope otherwise." (We call this "flow
scoping.") The formal rules are sketched out here:
http://cr.openjdk.java.net/~briangoetz/amber/pattern-semantics.html
(and, big surprise, they bear a significant resemblance to the "definite
assignment" rules.)
> But this begs the question: What is the limit of the ability to
> deduce the scope. If the previously mentioned expression works,
> then I would naively expect that javac would evaluate it this way:
> if the "instanceof expression" is false and the complete condition
> might evaluate to true with any combination of true/false for the
> other parts of the boolean expression, then then the newly declared
> variable is not in scope for the true path (similarly for the else path).
>
> If my above guess is true, then I would expect
> `if (!(!(obj instanceof String s) || myCondition))`
> to give me the `s` for the true path.
>
The rules are well defined and compositional, so it doesn't really
matter how complex the expression you give the compiler; it will apply
them and determine the scope of your bindings (which might not be a
contiguous scope.) So the "limit" is more likely to be in your own head
than in the language.
More information about the compiler-dev
mailing list