JEP 305 - Pattern Matching for instanceof (Preview)

Brian Goetz brian.goetz at
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:

(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