Java: Pattern Matching for instanceof
This article describes a preview feature, JEP draft: Pattern Matching for instanceof (Preview 2). If you want to play around with this, download and install JDK 15 available here and use the --enable-preview
. This article will be updated as the specification evolves.
Pattern matching for instanceof
allows you to bind a new variable as part of the expression:
if (obj instanceof String New variable declared…str) {
System.out.println("obj is a String of length " + str.length()…that can be used as a String
);
}
Scope of instanceof variable
The scope of the the bound variable depends on the context in which the expression is written. The compiler performs a (simple) flow analysis and allows you to use the variable where the instanceof
check holds true.
In the if
statement in the example above, the scope of str
is the true-branch.
if (obj instanceof String str) {
…
}
By negating the check, the scope becomes the false branch:
if (!(obj instanceof String str)) {
…
} else {
…
}
The variable is also used in the part of the expression where it is true. This means that you can implement a simple equals
method without explicit casting:
boolean equals(Object o) {
return o instanceof Point p && p.x == x && p.y == y;
}
Similarity to local variable initialization
Being able to introduce a variable as part of an expression like this is a unique feature. The scoping rules however, follow the same principles as the local variable initialization analysis performed by the compiler. Compare for example the first example in this article with this snippet:
String str;
if (obj instanceof String && (str = (String) obj) != null) {
// str accessible
}
// str not accessible (str may not have been initialized)
As you can see, the accessibility of str
is in practice the same, although the error message is ofcourse different.
Future functionality
What’s described in this article can barely be classified as pattern matching. As described in the JEP however, this new instanceof
functionality will be expanded to support nested matching for record types (JEP 359), and possibly other patterns.