Java 21 Unnamed Patterns and Variables is introduced as a preview feature JEP-443 that simplifies data processing. It enables the use of unnamed patterns and variables, denoted by an underscore character (_), to match components within data structures without specifying their names or types. Additionally, you can create variables that are initialized but remain unused in the code.
Let’s break this down in simpler terms:
Table of Contents
Introduction:
Before we dive into the world of Java records, let’s consider a situation where the conciseness of code
presents a challenge. In this instance, we will work with two record types: “Team” and “Member.”
record ProjectInfo(Long projectID, String projectName, Boolean isCompleted) {
// Constructor and methods (if any)
}
record TeamMemberInfo(Long memberID, String memberName, LocalDate joinDate, Boolean isActive, ProjectInfo projectInfo) {
// Constructor and methods (if any)
}
In Java, records provide a streamlined approach to create immutable data structures, particularly suitable for storing plain data. They eliminate the need for traditional getter and setter methods.
Now, let’s delve into how record patterns can simplify code by deconstructing instances of these records into their constituent components.
TeamMemberInfo teamMember = new TeamMemberInfo(101L, "Alice", LocalDate.of(1985, 8, 22), true, projectInfo);
if (teamMember instanceof TeamMemberInfo(Long id, String name, LocalDate joinDate, Boolean isActive, ProjectInfo projInfo)) {
System.out.printf("Team member %d joined on %s.", id, joinDate);
//Team member 101 joined on 1985-8-22
}
When working with record patterns, it’s often the case that we require only certain parts of the record and not all of them.
In above example, we exclusively used the “id” and “joinDate” components.
The presence of other components such as “name,” “isActive,” and “projInfo” doesn’t enhance clarity; instead, they add brevity without improving readability.
In Java 21, this new feature is designed to eliminate this brevity.
Exploring Unnamed Patterns and Variables
In Java 21, a new feature introduces the use of underscores (_) to represent record components and local variables, indicating our lack of interest in them.
With this new feature, we can revise the previous example more concisely as shown below.
It’s important to observe that we’ve substituted the “name,” “isActive,” and “projInfo” components with underscores (_).
if (teamMember instanceof TeamMemberInfo(Long id, _, LocalDate joinDate, _, _)) {
System.out.printf("Team member %d joined on %s.", id, joinDate); //Team member 101 joined on 1985-8-22
}
In a similar manner, we can employ the underscore character with nested records when working with the TeamMemberInfo record,
especially when we don’t need to use certain components. For example, consider the following scenario where we only
require the team member’s ID for specific database operations, and the other components are unnecessary.
if (teamMember instanceof TeamMemberInfo(Long id, _, _, _, _)) {
// Utilize the team member's ID
System.out.println("Team Member ID is: " + id); //Team Member ID is: 101
}
In this code, the underscore (_) serves as a placeholder for the components we don’t need to access
within the TeamMemberInfo record.
Starting from Java 21, you can use unnamed variables in these situations:
- Within a local variable declaration statement in a code block.
- In the resource specification of a ‘try-with-resources’ statement.
- In the header of a basic ‘for’ statement.
- In the header of an ‘enhanced for loop.’
- As an exception parameter within a ‘catch’ block.
- As a formal parameter within a lambda expression.
Java 21 Unnamed Patterns and Variables Practical Examples
Let’s dive into a few practical examples to gain a deeper understanding.
Example 1: Local Unnamed Variable
Here, we create a local unnamed variable to handle a situation where we don’t require the result.
int _ = someFunction(); // We don't need the result
Example 2: Unnamed Variable in a ‘catch’ Block
In this case, we use an unnamed variable within a ‘catch’ block to handle exceptions without utilizing the caught value.
String userInput = "Your input goes here";
try {
int number = Integer.parseInt(userInput);
// Use 'number'
} catch (NumberFormatException _) {
System.out.println("Invalid input: " + userInput);
}
Example 3: Unnamed Variable in a ‘for’ Loop
In the following example, we employ an unnamed variable within a simple ‘for’ loop, where the result of the runOnce() function is unused.
for (int i = 0, _ = runOnce(); i < array.length; i++) {
// ... code that utilizes 'i' ...
}
Example 4: Unnamed Variable in Lambda Expression
// Define a lambda expression with an unnamed parameter
Consumer<String> printMessage = (_) -> {
System.out.println("Hello, " + _);
};
// Use the lambda expression with an unnamed parameter
printMessage.accept("John"); //Hello, John
Example 5: Unnamed Variable in try-with-resources
try (var _ = DatabaseConnection.openConnection()) {
... no use of the established database connection ...
}
In all the above examples, where the variables remain unused and their names are irrelevant, we simply declare them without providing a name, using the underscore (_) as a placeholder. This practice enhances code clarity and reduces unnecessary distractions.
Conclusion
Java 21 introduces a convenient feature where you can use underscores (_) as placeholders for unnamed variables. This simplifies your code by clearly indicating that certain variables are intentionally unused within their specific contexts. You can apply unnamed variables in multiple situations, such as local variable declarations, ‘try-with-resources’ statements, ‘for’ loop headers, ‘enhanced for’ loops, ‘catch’ block parameters, and lambda expressions. This addition to Java 21 improves code readability and helps reduce unnecessary clutter when you need to declare variables but don’t actually use them in your code.