Master Java’s Unnamed Variables and Patterns: Cleaner Code in JDK 22+
This article explains the upcoming JDK 25 LTS release schedule, introduces Java's unnamed variables and patterns from JEP 443 and JEP 456, shows when and how to use them with practical code examples, outlines important restrictions, and helps developers write more concise and expressive Java code.
JDK 25 LTS is scheduled for GA on 2025‑09‑16, continuing the six‑month release cadence with LTS every two years (JDK 17 → 21 → 25). The article focuses on the most straightforward syntax improvement for the upgrade: unnamed variables and unnamed patterns introduced in JEP 443 (preview) and JEP 456 (final).
Why Unnamed Variables / Patterns
Clearly express intent: using _ is clearer than placeholder names like ignored or unused.
Eliminate boilerplate: reduces meaningless local names and pattern bindings, making code more compact.
Unified syntax: aligns with placeholder conventions in other languages such as Scala, Kotlin, and Python, lowering mental overhead.
What Can Be Used (Allowed)
Unnamed variables can appear in positions that declare a local variable but do not introduce a usable name in the scope: catch clause exception parameter try‑with‑resources resource variable
Lambda parameter
Enhanced for‑each loop variable
Any other local variable declaration where the name is never referenced
Unnamed patterns can be used in pattern matching to ignore components you do not care about:
Record deconstruction components instanceof / switch pattern matching (including nested and guarded when clauses)
Hands‑on Examples (Variables)
Ignore exception object
try {
riskyOperation();
} catch (IOException _) {
// Explicitly ignore the exception object
handleError();
}Ignore resource variable (still auto‑closed)
try (var _ = Files.newInputStream(Path.of("/tmp/data.bin"))) {
// Use external API or logger; no need to reference the resource name
process();
}Unused lambda parameter
// Single‑parameter unused
list.forEach(_ -> log.debug("visited"));
// One of two parameters unused
map.forEach((key, _) -> handle(key));
// Both parameters unused
BiConsumer<String, Integer> noop = (_, _) -> {};Enhanced for loop ignoring element value
for (Order _ : orders) {
metrics.increment();
}Hands‑on Examples (Patterns)
Ignore unneeded record components
record Point(int x, int y, int z) {}
if (obj instanceof Point(int x, int y, _)) {
use(x, y); // ignore z
}Pattern matching in switch that extracts only needed fields
record User(String name, int age, String email, boolean verified) {}
switch (user) {
case User(var name, _, _, true) -> welcome(name);
case User(_, var age, _, false) when age < 18 -> requireGuardian();
default -> audit(user);
}Combined and nested patterns
sealed interface Shape permits Circle, Rectangle {}
record Circle(double r, String color) implements Shape {}
record Rectangle(double w, double h, String color) implements Shape {}
String describe(Shape s) {
return switch (s) {
case Circle(double r, _) -> "circle r=" + r;
case Rectangle(double w, double h, _) -> "rect " + w + "x" + h;
};
}Important Restrictions (Don’ts)
Cannot reference _ : attempting to read or write the variable results in a compile‑time error.
Illegal examples: for (int _ = 0; _ < 10; _++) {}, System.out.println(_), _ = 1.
Only usable in declaration/binding positions such as catch parameters, lambda parameters, resource variables, and enhanced for element variables.
Multiple _ in the same scope are independent because they never introduce a name.
Since Java 9, _ is a reserved identifier and cannot be used as a field, method, or ordinary variable name.
When to Use / When Not to Use
Use when the value is truly irrelevant and using _ improves readability (e.g., unused catch or lambda parameters, ignored record components).
Use for side‑effect‑only constructs like try‑with‑resources where the resource name is never needed.
Do not use when the value helps readers understand the logic; hiding it reduces maintainability.
Do not use in classic counting for loops that require the loop variable.
Version and Status
JEP 443 (JDK 21, preview): Unnamed Patterns and Variables.
JEP 456 (JDK 22, final): Unnamed Variables & Patterns (enabled by default).
Summary
_is an explicit “I don’t care” commitment. It makes Java code cleaner and more consistent while avoiding the misleading practice of naming a variable that is never used. Understanding where it can be applied and its “cannot be referenced” limitation lets you safely replace boilerplate names with the expressive _.
References
JEP 456: Unnamed Variables & Patterns (JDK 22)
JEP 443: Unnamed Patterns and Variables (JDK 21 preview)
The Java Language Specification (relevant sections)
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
