Use type pattern matching in Java 17 and later
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.