Fundamentals 9 min read

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.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Master Java’s Unnamed Variables and Patterns: Cleaner Code in JDK 22+

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)

Javalanguage featuresPattern MatchingJDK 22Unnamed Variables
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.