Java 22 Unnamed Variables and Patterns with _
Introduction
Java code often has to declare a variable it will never use: the exception in a
OUTPUT of the above code
Explanation of the code
Unnamed patterns
In patterns,
OUTPUT of the above code
Rules
OUTPUT on compiling the above code
Summary
In this tutorial we saw how unnamed variables and patterns, final in Java 22, use
catch block which is handled the same way whatever it says, a lambda parameter the lambda ignores, or a record component in a record patternClick to read: record pattern which the code does not need. Giving such variables names like ignored or unused adds noise, and tools warn about unused variables. Java 22Click to read tutorial: Overview of New Features in Java 22 (JEP 456), after a preview in Java 21, finalized unnamed variables and patterns: the underscore _ declares a variable or pattern without a name, which says clearly "I do not need this". This tutorial explains them with examples - in catch blocks, lambdas, loops and try-with-resources, in record patterns and switch cases - and the rules for where _ can be used.
Unnamed variables
An unnamed variable is declared with _ instead of a name. It is allowed wherever a local variable is declared but its value is not needed -
Unused variables replaced by _
//UnnamedVariablesDemo.java
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
public class UnnamedVariablesDemo {
public static void main(String[] args) {
// catch: the exception itself is not needed
String input = "12a";
int value;
try {
value = Integer.parseInt(input);
} catch (NumberFormatException _) {
value = -1;
}
System.out.println("Parsed: " + value);
// lambda parameters: only one of two is used
BiFunction<String, Integer, String> firstOnly = (name, _) -> name.toUpperCase();
System.out.println(firstOnly.apply("tom", 42));
// enhanced for: count elements without using them
int count = 0;
for (String _ : List.of("a", "b", "c")) count++;
System.out.println("Counted " + count);
// several _ in the same scope are fine - they are all unnamed
Map<String, Integer> lengths = List.of("Java", "Duke").stream()
.collect(Collectors.toMap(s -> s, String::length, (a, _) -> a));
System.out.println(lengths);
}
}
Parsed: -1
TOM
Counted 3
{Java=4, Duke=4}
catch (NumberFormatException _)handles the exception without naming it. Since the variable has no name, it cannot be used by mistake, and IDEs do not warn about an unused variable.- In the lambda
(name, _) -> ...and the merge function(a, _) -> a, the underscore marks the parameter which is ignored. Several unnamed variables can exist in the same scope, unlike named ones. - Unnamed variables are also allowed for local variables with an initializer whose side effect matters (
var _ = queue.remove();), in basicforloops and in try-with-resources (try (var _ = lock.acquire())).
_ has two forms. An unnamed pattern, a bare _, matches any value of a record component without binding it. An unnamed pattern variable, such as Circle _, checks the type but does not bind a variable -
_ in record patterns and switch cases
//UnnamedPatternsDemo.java
public class UnnamedPatternsDemo {
sealed interface Shape permits Circle, Square, Rect { }
record Point(int x, int y) { }
record Circle(Point center, double radius) implements Shape { }
record Square(Point corner, double side) implements Shape { }
record Rect(Point corner, double width, double height) implements Shape { }
static String size(Shape shape) {
return switch (shape) {
case Circle(_, double r) -> "circle of radius " + r; // center not needed
case Square(_, double s) -> "square of side " + s;
case Rect(_, double w, double h) when w == h -> "a square-shaped rectangle";
case Rect _ -> "a rectangle"; // type only, no binding
};
}
static boolean isRound(Shape shape) {
return switch (shape) {
case Circle _ -> true;
case Square _, Rect _ -> false; // several patterns in one case: allowed with _
};
}
public static void main(String[] args) {
Shape[] shapes = {new Circle(new Point(0, 0), 2), new Square(new Point(1, 1), 3), new Rect(new Point(0, 0), 4, 4), new Rect(new Point(0, 0), 2, 5)};
for (Shape s : shapes) {
System.out.println(size(s) + ", round = " + isRound(s));
}
}
}
circle of radius 2.0, round = true square of side 3.0, round = false a square-shaped rectangle, round = false a rectangle, round = false
case Square _, Rect _ shows a capability unnamed patterns made possible: a single case can list several patterns, as long as none of them binds a variable - because the code after the arrow could not know which variable was bound.
- An unnamed variable cannot be read - there is no name to read it by.
_cannot be used for fields, method parameters (but lambda parameters are fine) or anywhere a name is needed to refer to something.- Since Java 9,
_has been a reserved keyword, so no existing code can use it as an ordinary identifier.
Using _ where it is not allowed
//UnnamedErrors.java
public class UnnamedErrors {
int _ = 5; // fields cannot be unnamed
void method(String _) { } // method parameters cannot be unnamed
void read() {
var _ = 42;
System.out.println(_); // an unnamed variable cannot be used
}
}
UnnamedErrors.java:3: error: underscore not allowed here
int _ = 5; // fields cannot be unnamed
^
UnnamedErrors.java:5: error: underscore not allowed here
void method(String _) { } // method parameters cannot be unnamed
^
UnnamedErrors.java:9: error: underscore not allowed here
System.out.println(_); // an unnamed variable cannot be used
^
3 errors
_ to mark variables and pattern components which are not needed. We used unnamed variables in a catch block, lambda parameters and an enhanced for loop, and unnamed patterns in record patterns and switch cases - including a single case with several type patterns. Lastly, we went through the rules, with the compiler errors for using _ where it is not allowed. Next, read about launching multi-file source-code programsClick to read tutorial: Java 22: Run Multi-File Programs Without Compiling.Continue Reading Java 22 to 25 Tutorials
Overview of New Features in Java 22Click to read tutorial: Overview of New Features in Java 22 Java 22 Foreign Function & Memory API TutorialClick to read tutorial: Java 22 Foreign Function & Memory API Tutorial Java 22: Run Multi-File Programs Without CompilingClick to read tutorial: Java 22: Run Multi-File Programs Without Compiling Overview of New Features in Java 23Click to read tutorial: Overview of New Features in Java 23 Overview of New Features in Java 24Click to read tutorial: Overview of New Features in Java 24 Overview of New Features in Java 25Click to read tutorial: Overview of New Features in Java 25 Java 23 Markdown Documentation CommentsClick to read tutorial: Java 23 Markdown Documentation Comments Java 24 Stream Gatherers Tutorial with ExamplesClick to read tutorial: Java 24 Stream Gatherers Tutorial with Examples Java 24 Class-File API Tutorial with ExamplesClick to read tutorial: Java 24 Class-File API Tutorial with Examples
Overview of New Features in Java 22Click to read tutorial: Overview of New Features in Java 22 Java 22 Foreign Function & Memory API TutorialClick to read tutorial: Java 22 Foreign Function & Memory API Tutorial Java 22: Run Multi-File Programs Without CompilingClick to read tutorial: Java 22: Run Multi-File Programs Without Compiling Overview of New Features in Java 23Click to read tutorial: Overview of New Features in Java 23 Overview of New Features in Java 24Click to read tutorial: Overview of New Features in Java 24 Overview of New Features in Java 25Click to read tutorial: Overview of New Features in Java 25 Java 23 Markdown Documentation CommentsClick to read tutorial: Java 23 Markdown Documentation Comments Java 24 Stream Gatherers Tutorial with ExamplesClick to read tutorial: Java 24 Stream Gatherers Tutorial with Examples Java 24 Class-File API Tutorial with ExamplesClick to read tutorial: Java 24 Class-File API Tutorial with Examples