Use type pattern matching in Java 17 and later

Alonso Del Arte
2 min readJul 18, 2024

--

Photo by Benjamin Zanatta on Unsplash

Experienced Java developers can probably think of a few examples in which they wrote something along these lines:

        if (obj instanceof T) {
T typedObj = (T) obj;
// TODO: Do something with typedObj
}

In this example, you believe that obj is an instance of T, but for whatever reason, the compiler is not quite convinced of this fact. At this point, the compiler considers that obj might be an instance of some superclass of T, up to and including java.lang.Object.

Then, whatever fields and functions are offered by T which are not offered by the superclasses, those are inaccessible for obj. It is therefore necessary to cast obj to T.

Or at least that’s the case in the long term support (LTS) releases Java 8 and Java 11.

The compiler is smart enough to understand that, for example, if a particular object has been proven to not be null, it is no longer necessary to give a warning for possibly dereferencing a null pointer on later mentions of that object in the pertinent scope.

So it would be nice if the compiler was also able to understand that an object really is of a specific subtype after an If statement with the instanceof operator.

To that end, a preview feature was included in Java 14 (not an LTS release, see JEP 305) that makes this kind of thing more concise. The feature was finalized in Java 16 (also not LTS, see JEP 394) and made its first appearance in an LTS release with Java 17.

        if (obj instanceof T typedObj) {
// TODO: Do something with typedObj
}

The If statement elides into itself the casting of obj to the expected type.

So we saved one line. Big deal. But we also reduced the possibility for mistakes and unexpected class cast exceptions (such as by casting something to the wrong type).

It may or may not be obvious to you that in the example the typedObj object is only available in the scope of the If statement’s True branch. That object is not available in the False branch because thenobj might reasonably be of some other type.

All of the foregoing about superclasses is also applicable to implemented interfaces. Like, for example, getting something out of the system clipboard. The getContents() function returns an object of a class implementing the Transferable interface.

Suppose your program will only operate on the clipboard if the clipboard contains text. Then you might write an If statement that checks if the getContents() function returns a StringSelection, which is one of a few classes in the Java Development Kit implementing the Transferable interface.

I don’t entirely like this syntax for type matching with instanceof, but I certainly prefer it to having to explicitly cast anything.

--

--

Alonso Del Arte
Alonso Del Arte

Written by Alonso Del Arte

is a Java and Scala developer from Detroit, Michigan. AWS Cloud Practitioner Foundational certified

No responses yet