Back to Java 24/25 Preview
Q7Question 7 of 8

What are unnamed variables and patterns?

Key Concepts
  • The underscore _ is used for variables you intentionally do not use, signaling intent to the compiler and readers
  • Five use cases: catch blocks, enhanced for-loops, lambda parameters, record pattern bindings, and try-with-resources
  • _ is not a real variable: you cannot read from it, and it causes a compile error if you try
  • Multiple _ bindings in the same scope do not conflict, unlike regular variables
  • Eliminates IDE warnings for unused variables and makes code intent explicit
  • Final in Java 22 via JEP 456
  • Especially useful with record patterns where you may ignore most components

Definition

The underscore _ is used for intentionally unused variable bindings in catch blocks, for-loops, lambdas, and pattern matches, eliminating IDE warnings and documenting intent.
  • Unnamed variable – _ declares a variable binding that is intentionally not used; the compiler and readers know it is ignored on purpose.
  • Not a variable – you cannot read from _; attempting to use it in an expression causes a compile error.
  • Multiple allowed – multiple _ bindings in the same scope do not conflict, unlike regular variable names.
  • Use cases – catch (IOException _), for (var _ : list), (_, value) -> process(value), case Trade(var _, var _, var amount, var _), try (var _ = resource).
  • Final in Java 22 – JEP 456.

When the bank processes a transaction, sometimes it needs only the amount, not the customer name. Before, the form required writing a name in every field even if you would never look at it, and the quality inspector flagged the unused field. With _, you write "intentionally blank" in the name field. No warning, clear intent.

Understanding the Concepts

What are unnamed variables and patterns?

The underscore _ is not a real variable name. You cannot read from it. It signals to the compiler and future readers that this binding is deliberately ignored. You can use _ multiple times in the same scope without conflict.

Use case 1: Catch blocks

JAVA
try {
    tradeService.settle(trade);
} catch (SettlementException _) {
    // We handle the error but do not inspect the exception object
    log.error("Settlement failed for trade {}", trade.getTradeId());
    trade.setStatus("FAILED");
}

Use case 2: Enhanced for-loops

JAVA
// Count iterations without using the element
int count = 0;
for (var _ : trades) {
    count++;
}

Use case 3: Lambda parameters

JAVA
// Map.forEach: we only need the value, not the key
tradesBySymbol.forEach((_, trades) -> {
    log.info("Processing {} trades", trades.size());
});

Use case 4: Record pattern bindings

JAVA
record Trade(String tradeId, String symbol, java.math.BigDecimal amount, String status) {}

// We only need the amount: ignore tradeId, symbol, and status
if (obj instanceof Trade(var _, var _, var amount, var _)) {
    processFee(amount);
}

// In switch:
String classify(Object obj) {
    return switch (obj) {
        case Trade(var _, var _, var amount, var _) when amount.compareTo(limit) > 0
            -> "LARGE TRADE";
        case Trade(var _, var _, var amount, var _)
            -> "NORMAL TRADE";
        default -> "UNKNOWN";
    };
}

Use case 5: Try-with-resources

JAVA
// Resource is held for its scope but never referenced
try (var _ = openConnection()) {
    // Connection is open for the duration of this block
    processAll();
}
// Connection closed automatically

Why can multiple _ appear in the same scope?

JAVA
// Three unnamed bindings in one pattern: no conflict
case Trade(var _, var _, var amount, var _) -> process(amount);

// Regular variables would conflict:
// case Trade(var a, var a, var amount, var a) → COMPILE ERROR: duplicate variable 'a'

What are common mistakes?

JAVA
// WRONG: trying to read from _
catch (IOException _) {
    log.error(_.getMessage());  // COMPILE ERROR: cannot read from _
}

// WRONG: using _ as a regular variable name (Java 9+ reserved)
String _ = "hello";  // COMPILE ERROR since Java 9

What should a senior engineer know?

  • _ was a valid identifier in Java 8 and earlier. It was reserved as of Java 9 and given this new purpose in Java 22.
  • Unnamed variables are purely about code cleanliness and intent documentation. They do not change runtime behavior.
  • In record patterns where a record has 5+ components, _ keeps the pattern readable by showing which fields matter.

What are common interview follow-up questions?

  • Is _ a keyword? (It is a reserved name for unnamed variables, not a traditional keyword.)
  • Can you use _ in a method parameter? (Yes, as of Java 22: void handle(Event _).)
  • Does _ have a value? (No. It is a discard. You cannot read it.)

Visual Overview

DIAGRAM
  Unnamed Variables Usage:

  catch (IOException _)          → ignore exception variable
  for (var _ : list)             → ignore loop element
  (_, value) -> use(value)       → ignore lambda param
  case Trade(_, _, amt, _)       → ignore record fields
  try (var _ = resource)         → ignore resource variable

  All signal: "I know this exists, I do not need it."
  Cannot read from _. Multiple _ allowed in same scope.

Key Takeaway

Unnamed variables (_, JEP 456, Java 22) let you declare a binding that you intentionally do not use. The underscore signals both to the compiler and to future readers that this variable is deliberately ignored. Before JEP 456, every catch block, for-loop, and lambda parameter required a named variable even if it was never read, creating IDE warnings and noise.

Five use cases cover the common scenarios: catch (IOException _) when you handle the error without inspecting the exception, for (var _ : list) when you count iterations, (_, value) -> process(value) when a lambda ignores one parameter, case Trade(var _, var _, var amount, var _) when destructuring records and only needing some fields, and try (var _ = resource) when holding a resource for its scope without referencing it.

The key rules: _ is not a real variable. You cannot read from it (compile error if you try). Multiple _ bindings in the same scope do not conflict, which is essential for record patterns where you might ignore 4 out of 5 components. The feature is purely about code cleanliness and intent documentation.

Remember one sentence: use _ for intentionally unused variables in catch, for, lambda, and pattern bindings to eliminate warnings and document intent.

---

Share
Use ← → arrow keys to navigate