JEP 443, Unnamed Patterns and Variables (Preview), has been Completed from Targeted status for JDK 21. This preview JEP proposes to "enhance the language with unnamed patterns, which match a record component without stating the component's name or type, and unnamed variables, which can be initialized but not used." Both of these are denoted by the underscore character, as in r instanceof _(int x, int y)
and r instanceof _
. This is a preview language feature.
Unnamed patterns are designed to streamline data processing, particularly when working with record classes. They allow developers to elide the type and name of a record component in pattern matching, which can significantly improve code readability. For example, consider the following code snippet:
if (r instanceof ColoredPoint(Point p, Color c)) {
// ...
}
In this instance, if the Color c
component is not needed in the if block, it can be laborious and unclear to include it in the pattern. With JEP 443, developers can simply omit unnecessary components, resulting in cleaner, more readable code:
if (r instanceof ColoredPoint(Point p, _)) {
// ...
}
Unnamed variables are useful in scenarios where a variable must be declared, but its value is not used. This is common in loops, try-with-resources statements, catch blocks, and lambda expressions. For instance, consider the following loop:
for (Order order : orders) {
if (total < limit) total++;
}
In this case, the order
variable is not used within the loop. With JEP 443, developers can replace the unused variable with an underscore, making the code more concise and clear:
for (_ : orders) {
if (total < limit) total++;
}
Unnamed patterns and variables are a preview feature, disabled by default. To use it, developers must enable the preview feature to compile this code, as shown in the following command:
javac --release 21 --enable-preview Main.java
The same flag is also required to run the program:
java --enable-preview Main
However, one can directly run this using the source code launcher. In that case, the command line would be:
java --source 21 --enable-preview Main.java
The jshell option is also available but requires enabling the preview feature as well:
jshell --enable-preview
Let’s look at a few more advanced use cases of unnamed patterns and variables introduced in JEP 443:
Unnamed patterns can be particularly useful in nested pattern-matching scenarios where only some components of a record class are required. For example, consider a record class ColoredPoint
that contains a Point
and a Color
. If you only need the x
coordinate of the Point
, you can use an unnamed pattern to omit the y
and Color
components:
if (r instanceof ColoredPoint(Point(int x, _), _)) {
// ...
}
Unnamed pattern variables can be beneficial in switch statements where the same action is executed for multiple cases, and the variables are not used. For example:
switch (b) {
case Box(RedBall _), Box(BlueBall _) -> processBox(b);
case Box(GreenBall _) -> stopProcessing();
case Box(_) -> pickAnotherBox();
}
In this example, the first two cases use unnamed pattern variables because their right-hand sides do not use the box's component. The third case uses the unnamed pattern to match a box with a null component.
Unnamed variables can be used in lambda expressions where the parameter is irrelevant. For example, in the following code, the lambda parameter v
is not used, so its name is irrelevant:
stream.collect(Collectors.toMap(String::toUpperCase, _ -> "No Data"));
In try-with-resources statements, a resource represents the context in which the code of the try block executes. If the code does not use the context directly, the name of the resource variable is irrelevant. For example:
try (var _ = ScopedContext.acquire()) {
// No use of acquired resource
}
Unnamed variables can be used in catch blocks where the name of the exception parameter is irrelevant. For example:
try {
int i = Integer.parseInt(s);
} catch (NumberFormatException _) {
System.out.println("Bad number: " + s);
}
Notably, the underscore character was previously valid as an identifier in Java 10. However, since Java 8, the use of underscore as an identifier has been discouraged, and it was turned into a compile-time error in Java 9. Therefore, it is assumed that a minimal amount of existing and actively maintained code uses underscore as a variable name. In instances where such code does exist, it will need to be modified to avoid using an underscore as a variable name.
Given this, JEP 443 is a significant step towards making Java code more readable and maintainable. This is particularly beneficial in complex data structures where the shape of the structure is just as important as the individual data items within it. By allowing developers to omit unnecessary components and variables, it reduces code clutter and makes the code easier to understand. As developers gain more experience with this feature, it is expected to become an integral part of Java programming.
Community comments
Personally, I don’t think unnamed patterns is a good idea in Java
by John Dogget,
Re: Personally, I don’t think unnamed patterns is a good idea in Java
by A N M Bazlur Rahman,
Personally, I don’t think unnamed patterns is a good idea in Java
by John Dogget,
Your message is awaiting moderation. Thank you for participating in the discussion.
In most scenarios in Java, you should not declare a never-used variable. Unlike golang, methods can return multiple variables and some of them may not be used. Therefore, unnamed variables are useful for golang as they can reduce unnecessary memory consumption.
I suggest that engineers should review their code and ensure its rationality, rather than adding the feature of unnamed variables in Java. This could result in engineers producing more garbage code.
Re: Personally, I don’t think unnamed patterns is a good idea in Java
by A N M Bazlur Rahman,
Your message is awaiting moderation. Thank you for participating in the discussion.
I understand your concern regarding the introduction of unnamed variables in Java. However, considering the growing emphasis on data-oriented programming in Java, where records and pattern matching are heavily utilized, unnamed variables could potentially prove useful, particularly in deconstructing values.
That said, the decision to use a specific feature always boils down to personal preference and coding style. Furthermore, with code review being a fundamental aspect of software development, potential issues can be identified and rectified efficiently. So, despite the potential drawbacks, there might be a place for this feature in Java, provided it is used responsibly.