Java 23 introduces unnamed variables and unnamed patterns, which improve code readability and maintainability by allowing developers to omit unused variables and patterns. These features reduce clutter and make it easier to focus on the relevant parts of the code.
Unnamed Variables
Unnamed variables are variables that can be declared but not used. They are useful when the side effect of a statement is more important than the variable itself. These variables are denoted using the underscore character (_
).
Example: Using Unnamed Variables in a For Loop
Consider a simple iteration through an array:
String[] names = {"Alice", "Bob", "Charlie", "David"};
int count = 0;
for (String _ : names) {
count++;
}
System.out.println("Total names: " + count);
Here, _
replaces the unused loop variable, making it clear that the loop only counts the elements.
Valid Declarations of Unnamed Variables
Unnamed variables can be used in several contexts:
-
Local Variable Declaration:
record Transaction(String id, double amount) { } static List<Transaction> filterTransactions(Queue<Transaction> queue, int limit) { var filtered = new ArrayList<Transaction>(); try { while (limit > 0) { Transaction _ = queue.remove(); Transaction _ = queue.remove(); filtered.add(queue.remove()); limit--; } } catch (NoSuchElementException _) { // Do nothing } return filtered; }
-
Try-with-Resources Statement:
static void checkFile(String filePath) { try (var _ = new BufferedReader(new FileReader(filePath))) { // Do nothing } catch (IOException e) { e.printStackTrace(); } }
-
For Loop Header:
Function<Integer, String> logEffect = n -> { System.out.println("Processing: " + n); return "Done"; }; for (int i = 0, _ = logEffect.apply(100); i < 5; i++) { System.out.println("Step: " + i); }
-
Exception Parameter in Catch Blocks:
static void parseInteger(String input) { try { int num = Integer.parseInt(input); System.out.println(num + " is a valid number"); } catch (NumberFormatException _) { System.out.println("Invalid number format"); } }
-
Lambda Parameter:
record Circle(double radius) {} record Drawing(String id, Circle shape) {} static Map<String, String> getDrawingIDs(List<Drawing> drawings) { return drawings.stream().collect(Collectors.toMap(Drawing::id, _ -> "UNKNOWN")); }
Unnamed Patterns
Unnamed patterns simplify pattern matching by omitting unused variables in record patterns.
Example: Eliminating Unused Pattern Variables
Without Unnamed Patterns
record Coordinates(double latitude, double longitude) {}
enum Status { ACTIVE, INACTIVE, PENDING }
record Location(Coordinates coord, Status status) {}
double calculateDistance(Object loc1, Object loc2) {
if (loc1 instanceof Location(Coordinates c1, Status s1) &&
loc2 instanceof Location(Coordinates c2, Status s2)) {
return Math.sqrt(Math.pow(c2.latitude - c1.latitude, 2) + Math.pow(c2.longitude - c1.longitude, 2));
}
return -1;
}
With Unnamed Patterns
double calculateDistance(Object loc1, Object loc2) {
if (loc1 instanceof Location(Coordinates c1, _) &&
loc2 instanceof Location(Coordinates c2, _)) {
return Math.sqrt(Math.pow(c2.latitude - c1.latitude, 2) + Math.pow(c2.longitude - c1.longitude, 2));
}
return -1;
}
Here, _
replaces the unused Status
components, making the code cleaner.
Restrictions on Unnamed Patterns
-
You cannot use
_
as a top-level pattern:
// Compiler error if (loc1 instanceof _) { // ... }
-
You cannot use
_
as a reference:
// Compiler error if (loc1 instanceof Location(Coordinates c1, Status _)) { System.out.println("Status: " + _); // Invalid }
Using Unnamed Patterns in Switch Statements
Unnamed patterns are useful in switch expressions and statements:
sealed interface User permits Admin, Guest, Member { }
record Admin(String name, int accessLevel) implements User { }
record Guest(String name) implements User { }
record Member(String name) implements User { }
void displayAccess(User user) {
switch (user) {
case Admin a -> System.out.println("Access Level: " + a.accessLevel());
case Guest _, Member _ -> System.out.println("Limited Access");
}
}
Using multiple unnamed patterns in case labels helps group similar cases together, improving readability.
Conclusion
Unnamed variables and patterns in Java 23 enhance code clarity by allowing developers to omit unnecessary variables and patterns. They improve readability, reduce redundancy, and streamline pattern matching. By adopting these new features, developers can write cleaner and more maintainable Java code.
Top comments (0)