Unnamed variables & patterns in Java
Java 22 _ for unused variables and pattern components.
Say "don't care"
Java 22 (JEP 456) made the underscore **_ official for variables you won't use: in catch blocks, lambda parameters, loops and more. It tells readers, and the compiler, that the value is intentionally unused**.
for (var _ : orders) { count++; }
map.forEach((_, v) -> System.out.println(v));
try { save(); }
catch (IOException _) { retryLater(); }In patterns too
In a record pattern, _ matches a component without binding it: case Point(var x, _) says "I only care about x". It works when nested as well: case Box(Point(var x, _), _) ->.
Your turn
What does this print?
record Pair(String a, String b) {}
void main() {
Object o = new Pair("left", "right");
if (o instanceof Pair(_, var b)) {
System.out.println(b);
}
}rightleftCompile error
Show the answer
right. The _ matches the first component without binding it, and var b binds the second one.
Can you read it?
An unnamed variable gets a value. What happens when you print it?
int _ = 5;
System.out.println(_);50Compile error
Show the answer
Compile error. _ never introduces a name, so there's nothing to refer to. You can **never read from _**: that's the whole promise.
As many as you like
Because _ never declares a name, it can't clash: **several _ in the same scope are fine**. That's what makes (_, _) -> 0 legal, where two named parameters would need two different names.
Naming the unused
try {
n = Integer.parseInt(s);
} catch (NumberFormatException ignored) {
n = -1;
}"ignored" is still a real variable: someone can read it later, and readers must check whether anyone does.
try {
n = Integer.parseInt(s);
} catch (NumberFormatException _) {
n = -1;
}Intent is explicit, and the compiler stops anyone from reading it.
Intent, not speed
_ is about clarity and safety, not performance: it doesn't make code faster or free memory sooner, and nothing forces you to use it. Its payoff is in reviews: unused-variable warnings disappear, and readers instantly see which values were dropped on purpose.
Key takeaways
- catch (NumberFormatException _) { ... }
- case Box(Point(var x, _), _) ignores components
- Many _ per scope are fine; _ can never be read
- Final since Java 22 (JEP 456)
_ has a twisty history: Java 8 warned when you used it as a name, Java 9 made that an error, and Java 22 brought it back meaning "unnamed".
Practice questions
What does this print?
record Point(int x, int y) {}
void main() {
Object o = new Point(5, 8);
if (o instanceof Point(var x, _)) {
System.out.println(x);
}
}- 5
- 8
- Point[x=5, y=8]
- Compile error
Check your answer
5. _ matches the y component without binding it, so only x (5) is available.
What does this print?
String s = "12x";
int n;
try {
n = Integer.parseInt(s);
} catch (NumberFormatException _) {
n = -1;
}
System.out.println(n);- -1
- 12
- Throws NumberFormatException
- Compile error
Check your answer
-1. "12x" isn't a valid int, so the catch block runs. Naming the exception _ documents that its details aren't needed.