last modified May 28, 2025
This article explains how to use the underscore (_) to denote
unused variables in Java, a feature introduced in Java 21 (JEP 443) to help
developers explicitly ignore unused parameters.
In Java, we often encounter situations where we need to declare parameters or variables that we don't actually use:
Traditionally, developers would either:
unused or ignore)
Java 21 introduced the underscore (_) as a special identifier to
mark intentionally unused variables. Commonly known as a "discard" in other
languages, it enhances code clarity by explicitly signaling that the variable is
unnecessary, leading to cleaner and more readable syntax.
The underscore can be used in several contexts:
// Lambda parameters
(param1, _) -> expression
// Pattern matching
if (obj instanceof String _) { ... }
// Exception handling
try { ... } catch (Exception _) { ... }
Key characteristics:
_ can only appear once in a scope (we can't have multiple _ in same scope)
Using _ in lambda parameters allows us to ignore parameters we
don't need. This is particularly useful in functional programming contexts where
we may only care about one of the parameters in a lambda expression.
void main() {
Map<String, Integer> scores = Map.of("Alice", 90, "Bob", 85);
// Only using the key, ignoring the value
scores.forEach((name, _) -> System.out.println("Student: " + name));
// Only using the value, ignoring the key
scores.forEach((_, score) -> System.out.println("Score: " + score));
}
This example shows how to ignore either the key or value in a
Map.forEach operation.
Pattern matching allows us to match types and structures in a more concise way.
We can use _ to ignore values in pattern matching, making our code
more readable when we only care about the type or structure, not the actual
value.
void process(Object obj) {
switch (obj) {
case String _ -> System.out.println("It's a String");
case Integer _ -> System.out.println("It's an Integer");
case Double _ -> System.out.println("It's a Double");
default -> System.out.println("Unknown type");
}
}
void main() {
process("Hello");
process(42);
process(3.14);
process(new Object());
}
Here we use _ to match types without binding the actual value to a
variable.
Using _ in exception handling when we don't need the exception
object:
void readFile() {
try {
// File reading operation that might fail
String fileName = "words.txt";
String content = Files.readString(Path.of(fileName));
System.out.println(content);
} catch (IOException _) {
System.out.println("Error occurred while reading file");
// Don't need the exception details
}
}
void main() {
readFile();
}
This shows how to handle an exception when we don't need to access the exception object.
In pattern matching with records, we can also use _ to ignore
fields we don't care about.
record Point(int x, int y) {}
void printX(Point p) {
if (p instanceof Point(int x, _)) {
System.out.println("X coordinate: " + x);
}
}
void main() {
printX(new Point(5, 10));
}
Here we deconstruct a Point record but only care about the
x coordinate.
When to use _:
When not to use _:
Important notes about compatibility:
_ was a valid identifier in Java 1.0-20_ is a special token when used as a variable name_ as a variable name will break in Java 21+_ variables to something elseJEP 443: Unnamed Patterns and Variables
In this article we've explored Java's unnamed variable pattern (_),
a simple but powerful feature that makes code more readable by explicitly
marking unused variables.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Java tutorials.