Lesson 24: Unnamed Variables & Patterns (_ for Unused Values) – Java 21+

Java 21 introduced Unnamed Variables (_) and Unnamed Patterns, making code cleaner and more readable by ignoring unused values. These features improve pattern matching, lambda expressions, and destructuring assignments.


1. What Are Unnamed Variables (_)?

Unnamed Variables (_) are placeholders for values you don’t need.
They improve readability by making it clear that a value is unused.
They work in enhanced for loops, try-with-resources, and lambda expressions.


2. Before Java 21: Ignoring Unused Variables (Messy Code)

🔴 Before Java 21, unused values had to be named even if they weren’t needed.

📌 Example: Before Java 21 (Naming Unused Variables)

record User(String name, int age) { }

public class Main {
    public static void main(String[] args) {
        User user = new User("Alice", 25);

        // ❌ 'age' is not used, but we must name it
        String name = user.name();
        int age = user.age();  // Unused variable
    }
}

You still had to declare age even though it’s not used.


3. Java 21+ Solution: Using _ to Ignore Unused Variables

🟢 Now you can use _ instead of declaring a variable you don’t need!

📌 Example: Using _ to Ignore Unused Variables

record User(String name, int age) { }

public class Main {
    public static void main(String[] args) {
        User user = new User("Alice", 25);

        // ✅ Only extract 'name', ignore 'age'
        String name = user.name();
        int _ = user.age();  // Unused value (No warning, No error)
    }
}

No warnings for unused variables!
Cleaner and more readable.


4. Unnamed Patterns in switch and record Matching

🚀 Unnamed Patterns allow _ in pattern matching and record destructuring.

📌 Example: Ignoring Unused Fields in record Matching

record User(String name, int age) { }

public class Main {
    public static void main(String[] args) {
        User user = new User("Alice", 25);

        if (user instanceof User(String name, _)) { // ✅ Ignore 'age'
            System.out.println("User: " + name);
        }
    }
}

Output:

User: Alice

You don’t need to name the age field if it’s not used!


5. Using _ in Enhanced for Loops

📌 Example: Ignoring Index in Loops (Before vs. After Java 21)

🔴 Before Java 21 (Unused Loop Variables Needed)

for (int i = 0; i < 10; i++) {
    System.out.println("Hello!");
}

🟢 Java 21+ (Ignore i with _)

for (int _ = 0; _ < 10; _++) {
    System.out.println("Hello!");
}

The loop still runs, but _ makes it clear that i is not used.


6. Using _ in Try-with-Resources

📌 Example: Ignoring a Resource in try-with-resources

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        try (BufferedReader _ = new BufferedReader(new FileReader("data.txt"))) {
            System.out.println("Reading file...");
        }
    }
}

The resource is still opened and closed properly, but _ indicates that it is not directly used.


7. Using _ in Lambda Expressions

📌 Example: Ignoring Unused Lambda Parameters

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("Alice", "Bob", "Charlie");

        names.forEach((_ -> System.out.println("Processing...")));
    }
}

Output:

Processing...
Processing...
Processing...

No need to name the variable if it’s unused in the lambda.


8. When Should You Use _?

🚀 Use _ when:
✔ You have unused method parameters in lambdas.
✔ You are ignoring values in record destructuring.
✔ You want cleaner loops or try-with-resources.

🚨 Do NOT use _ if:
❌ You actually need to use the variable.
❌ You are using Java 20 or earlier (This feature is Java 21+ only).


9. Comparison: Before Java 21 vs. Java 21+ (_)

FeatureBefore Java 21Java 21+ (_)
Ignoring Unused Variables❌ Had to name them_ makes it clear
Record Pattern Matching❌ Had to extract all fields✅ Use _ for unused fields
Lambda Expressions❌ Named variables even if unused_ for ignored parameters

Lesson Reflection

  1. How does _ improve code readability and reduce warnings for unused variables?
  2. Why is _ useful in record pattern matching?
  3. Can you think of a real-world scenario where ignoring values with _ is helpful?

Answers to Reflection Questions on Unnamed Variables & Patterns (_) – Java 21+


1️⃣ How does _ improve code readability and reduce warnings for unused variables?

Before Java 21, you had to declare variables even if they were unused.
Using _ makes it clear that a value is intentionally ignored, improving readability.
Avoids compiler warnings about unused variables.

📌 Example: Before Java 21 (Unused Variable Warning)

record User(String name, int age) { }

public class Main {
    public static void main(String[] args) {
        User user = new User("Alice", 25);

        String name = user.name();
        int age = user.age(); // ❌ Unused variable warning
    }
}

🚨 Problem: The compiler warns about age being unused.

🟢 Java 21+ Solution: Use _ to Ignore Unused Values

record User(String name, int age) { }

public class Main {
    public static void main(String[] args) {
        User user = new User("Alice", 25);

        String name = user.name();
        int _ = user.age();  // ✅ No warning, `_` means we intentionally ignore it
    }
}

No more warnings, and the code is more readable!


2️⃣ Why is _ useful in record pattern matching?

Before Java 21, you had to extract all fields in record pattern matching.
With _, you can ignore fields you don’t need.

📌 Example: Using _ in Record Pattern Matching

record User(String name, int age) { }

public class Main {
    public static void main(String[] args) {
        User user = new User("Alice", 25);

        if (user instanceof User(String name, _)) { // ✅ Ignore 'age'
            System.out.println("User: " + name);
        }
    }
}

Output:

User: Alice

Makes it clear that age is intentionally ignored.


3️⃣ Can you think of a real-world scenario where ignoring values with _ is helpful?

🚀 Scenario 1: Ignoring Index in Loops
✔ In some cases, you need to iterate without using the loop index.
_ makes it clear that the index is unused.

📌 Example: Ignoring Loop Index

for (int _ = 0; _ < 5; _++) {
    System.out.println("Running task...");
}

Output:

Running task...
Running task...
Running task...
Running task...
Running task...

No unnecessary variable names cluttering the loop!


🚀 Scenario 2: Ignoring Unused Lambda Parameters
✔ Some APIs require lambda parameters that aren’t needed.
_ makes it clear that a parameter is ignored.

📌 Example: Ignoring Lambda Parameters in forEach()

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("Alice", "Bob", "Charlie");

        names.forEach((_ -> System.out.println("Processing...")));
    }
}

Output:

Processing...
Processing...
Processing...

No need to name the variable if it’s unused!


🚀 Scenario 3: Ignoring Fields in JSON Processing
Imagine you are parsing a JSON API response but only need specific fields.

📌 Example: Ignoring Unneeded JSON Fields

record ApiResponse(String status, int code, String message, String data) { }

public class Main {
    public static void main(String[] args) {
        ApiResponse response = new ApiResponse("OK", 200, "Success", "{...}");

        if (response instanceof ApiResponse(_, _, String message, _)) {
            System.out.println("API Message: " + message);
        }
    }
}

Output:

API Message: Success

Only extracts message, ignoring other fields.


🔍 Key Takeaways

Using _ makes it clear when a value is intentionally ignored.
Prevents compiler warnings about unused variables.
Works great in loops, lambdas, record matching, and JSON processing.

The next Java 21+ feature: Sequenced Collections (List.of(), Map.of() order guarantee) 😊🚀

Java Sleep