Language selector

Pattern Matching - the beginning

Java 14 has a lot of new features. One of them (as preview feature) is pattern matching with instanceof. Some people programming in languages supporting the functional paradigm to some extent, e.g. Scala, Kotlin (not to mention Haskell) jumped high, full of joy ‘Yay, we gonna have match or when, extracting data, guards, deconstructors in companion objects and more!’ We’re greedy. Since Java 9 and with major releases every 6 months Java is more of a ‘baby steps’ approach (or slowly boiling frogs, if you will). And the first baby step having ‘pattern matching’ in name is JEP 305: Pattern Matching for instanceof (Preview). (If the switch expressions aren’t an earlier attempt to put some fire under this pot is another story, but at least the JEPs for switch expressions don’t mention that in their names.)

Matching by the type

In my opinion this JEP is a nice beginning to pattern matching, and it also allows eliminating ceremony and ‘obvious’ code. Let’s throw an eye™ in the code below in which we’re checking if an object is an Integer and if so, we double it:

1if (object instanceof Integer) {
2    Integer integer = (Integer) object;
3    int doubled = integer * 2;
4    //here we're doing something with doubled...
5}

Line 2 from the listing above is somewhat controversial to many and (let’s speak frankly) is a reason to say that ‘Java is full of ceremony’. Well, this might be somewhat true, because if in the first line we’ve already checked that ‘it must be an Integer’, then is the casting in the second line really needed? Can’t object be used as an Integerin line 2 right away? ‘C’mon, I know already it’s an Integer, you’ve let me into this if, what else do you want??!!1one’

Since Java 14 the JEP 305 mentioned earlier can help us. Using it we can rewrite the above code like this:

1 if (object instanceof Integer integer) {
2
3     int doubled = integer * 2;
4     //here we're doing something with doubled...
5 }
6 

What happened to line 2? Well, casting isn’t needed anymore. Now, instead of casting, all we need after typing instanceof <AClass> is to type a variable name for the variable if its type matches AClass. In this case if the object successfully matches AClass, inside the if block it will be visible as Integer integer. We may think like ‘casted alias’. And we don’t need the casting anymore.

Let’s get greedy

This isn’t over, my friends. Because we can use the matched object not only in the ‘if's body’, but also in the if's condition. Let’s assume we have a ‘business need’ to double the numbers, but only negative ones. The old-fashioned way of doing that would be:

1if (object instanceof Integer) {
2    Integer integer = (Integer) object;
3    if (integer < 0) {
4        int doubled = integer * 2;
5        //here we're doing something with doubled...
6    }
7}
In such a case, beside the casting in line 2, we also need to nest another check. IT’s getting nasty, isn’t it? We can try to make this code cleaner, we may try to extract the doubling method, and so on. Or we can use JEP 305 even more and write it like this:

1if (object instanceof Integer integer && integer < 0) {
2
3
4    int doubled = integer * 2;
5    //here we're doing something with doubled...
6
7}

This time two/three lines are gone (depends how we format and count the lines), but what’s more important we don’t have this nested block any more! (I intentionally left the blank lines for better readability and to make the lack of these lines more obvious. In the real code we don’t do that.)

In other words: we want to double our object if it matches the pattern “an integer and a negative one”. That’s why this JEP IMHO is named ‘pattern matching with instanceof’.

In the coming versions of Java we’re awaiting even more sophisticated forms of pattern matching, with deconstruction and other goodies. Until then I suggest playing with what we already have, using this example, for example.

In the next post I wrote how we should IMHO not use pattern matching with instanceof.

Language selector