Book Image

Java Coding Problems - Second Edition

By : Anghel Leonard
Book Image

Java Coding Problems - Second Edition

By: Anghel Leonard

Overview of this book

The super-fast evolution of the JDK between versions 12 and 21 has made the learning curve of modern Java steeper, and increased the time needed to learn it. This book will make your learning journey quicker and increase your willingness to try Java’s new features by explaining the correct practices and decisions related to complexity, performance, readability, and more. Java Coding Problems takes you through Java’s latest features but doesn’t always advocate the use of new solutions — instead, it focuses on revealing the trade-offs involved in deciding what the best solution is for a certain problem. There are more than two hundred brand new and carefully selected problems in this second edition, chosen to highlight and cover the core everyday challenges of a Java programmer. Apart from providing a comprehensive compendium of problem solutions based on real-world examples, this book will also give you the confidence to answer questions relating to matching particular streams and methods to various problems. By the end of this book you will have gained a strong understanding of Java’s new features and have the confidence to develop and choose the right solutions to your problems.
Table of Contents (16 chapters)
1
Text Blocks, Locales, Numbers, and Math
Free Chapter
2
Objects, Immutability, Switch Expressions, and Pattern Matching
14
Other Books You May Enjoy
15
Index

57. Introducing pattern matching

JDK 16 has introduced one of the major and complex features of Java, referred to as pattern matching. The future is wide open for this topic.

In a nutshell, pattern matching defines a synthetic expression for checking/testing whether a given variable has certain properties. If those properties are met, then automatically extract one or more parts of that variable into other variables. From this point forward, we can use those extracted variables.

A pattern matching instance (pay attention, this has nothing to do with design patterns) is a structure made of several components as follows (this is basically the pattern matching terminology):

  • The target operand or the argument of the predicate: This is a variable (or an expression) that we aim to match.
  • The predicate (or test): This is a check that takes place at runtime and aims to determine if the given target operand does or doesn’t have one or more properties (we match the target operand against the properties).
  • One or more variables are referred to as pattern variables or binding variables: these variables are automatically extracted from the target operand if and only if the predicate/test succeeds.
  • Finally, we have the pattern itself, which is represented by the predicate + binding variables.
Figure 2.31.png

Figure 2.31: Pattern matching components

So, we can say that Java pattern matching is a synthetic expression of a complex solution composed of four components: target operand, predicate/test, binding variable(s), and pattern = predicate + binding variable(s).

The scope of binding variables in pattern matching

The compiler decides the scope (visibility) of the binding variables, so we don’t have to bother with such aspects via special modifiers or other tricks. In the case of predicates that always pass (like an if(true) {}), the compiler scopes the binding variables exactly as for the Java local variables.

But, most patterns make sense precisely because the predicate may fail. In such cases, the compiler applies a technique called flow scoping. That is actually a combination of the regular scoping and definitive assignment.

The definitive assignment is a technique used by the compiler based on the structure of statements and expressions to ensure that a local variable (or blank final field) is definitely assigned before it is accessed by the code. In a pattern-matching context, a binding variable is assigned only if the predicate passes, so the definitive assignment aim is to find out the precise place when this is happening. Next, the regular block scope represents the code where the binding variable is in scope.

Do you want this as a simple important note? Here it is.

Important note

In pattern matching, the binding variable is flow-scoped. In other words, the scope of a binding variable covers only the block where the predicate passed.

We will cover this topic in Problem 59.

Guarded patterns

So far, we know that a pattern relies on a predicate/test for deciding whether the binding variables should be extracted from the target operand or not. In addition, sometimes we need to refine this predicate by appending to it extra boolean checks based on the extracted binding variables. We name this a guarded pattern. In other words, if the predicate evaluates to true, then the binding variables are extracted and they enter in further boolean checks. If these checks are evaluated to true, we can say that the target operand matches this guarded pattern.

We cover this in Problem 64.

Type coverage

In a nutshell, the switch expressions and switch statements that use null and/or pattern labels should be exhaustive. In other words, we must cover all the possible values with switch case labels.

We cover this in Problem 66.

Current status of pattern matching

Currently, Java supports type pattern matching for instanceof and switch, and record pattern-destructuring patterns for records (covered in Chapter 4). These are the final releases in JDK 21.