Java - Using Unnamed Variables and Patterns Examples

This tutorial shows you how to use unnamed variables and patterns introduced in Java 21.

If you write code using Java, sometimes you may find a situation where you are forced to write a name just because of the syntax. That may cause a lot of unused names in your code. As a solution, Java 21 introduced a new feature called unnamed variables and patterns. For the explanation, you can read the examples in this tutorial.

Unnamed Variables

If you don't want to give a variable a name because it's never been accessed, you can write an unnamed variable using an _ (underscore) symbol. Below are several cases where you can use unnamed variables.

Variable Assignments

For example, there is a List with several elements and we want to remove the first three values. It can be done by calling the removeFirst method three times. The method returns the removed value. Therefore, the first two removed values must be assigned to variables. Meanwhile, for the third variable, we only want to get the side effect of the method without knowing the result.

In that case, we can just remove the variable assignment. However, to consistently denote the result, the third removed value is also assigned to a variable although it's never used. While Java supports var keyword, there was no way to avoid naming the variable prior to Java 21.

  List<String> values = new ArrayList<>(){};
  values.add("one");
  values.add("two");
  values.add("three");
  values.add("four");

  String firstValue = values.removeFirst();
  String secondValue = values.removeFirst();
  String thirdValue = values.removeFirst();
  System.out.println("firstValue: " + firstValue);
  System.out.println("secondValue: " + secondValue);

While the code works as expected, an IDE or static analytic tool may give a warning related to the unused variables. Since Java 21, it's possible to avoid that warning by using an unnamed variable. Instead of giving the variable a name, just write an _ (underscore).

  String firstValue = values.removeFirst();
  String secondValue = values.removeFirst();
  String _ = values.removeFirst();

It's also allowed to write assignments to an unnamed variable multiple times. That will not cause a duplicate name error since _ is basically not a variable name.

  String firstValue = values.removeFirst();
  String _ = values.removeFirst();
  String _ = values.removeFirst();

Enhanced For Loop

In an enhanced for loop, usually the iterated elements can be accessed by using the name defined before :. In a few cases that do not require access to the iterated elements, the name can be replaced with _.

  int counter = 0;
  
  for (String _ : values) {
    counter++;
  }

Catch Block

When defining a catch block, usually the caught exception type is followed by a variable name. If the exception can be ignored completely, the variable name will be unused. As a solution, just write _ to replace the variable name.

  try {
    Integer.parseInt("x");
  } catch (Exception _) {
    System.out.println("Get Exception");
  }

If there are multiple catch blocks where the error objects are unused, defining multiple _ is possible as well.

  try {
    Integer.parseInt("x");
  } catch (NumberFormatException _) {
    System.out.println("Get NumberFormatException");
  } catch (Exception _) {
    System.out.println("Get Exception");
  }

Try-with-resources

In a try-with-resources block, usually there are one or more assignment statements inside the try bracket. If the reference to a resource is not necessary, just write _ instead of specifying a name.

  try (var _ = new Scanner(new File("file.txt"))) {
    System.out.println("File can be scanned");
  } catch (Exception ex) {
    System.out.println("File cannot be scanned");
  }

Lambda with irrelevant parameter

It's quite common to have a lambda with one or more arguments that are never accessed. Those unused arguments can be replaced with _.

  String lastValue = values.stream()
      .reduce((_, second) -> second)
      .orElse(null);
  System.out.println(lastValue);

Unnamed Patterns

Besides for unnamed variables, the _ symbol can also be used in unnamed patterns. Java's pattern matching supports checking whether the value of a field matches a specified type. However, it's quite common that we only want to match the type without getting the value of the field. This is where unnamed patterns can be useful.

instanceof Pattern Matching

The instanceof keyword in Java is used to check whether a value is an instance of a specified type.

With the addition of pattern matching support, instanceof can be used to check whether the field of a record matches a particular type. For checking only the field type without the need for extracting the value of the field, it's not necessary to define a name for the matched field.

For example, we have a record named Point with two fields whose type is Number.

  record Point(Number x, Number y) {}

The Number class has some sub types such as Integer, Float, and Double.

To check whether a variable is an instance of Point whose fields are Integer, we can use _ after the type instead of writing a name that will not be used. Meanwhile, if the type of a field doesn't need to be matched, just write _ without preceded by any type.

  Point point = new Point(0, 2);
  System.out.println(point instanceof Point(Integer _, Integer _));
  System.out.println(point instanceof Point(Integer x, _));

Switch Pattern Matching

The similar thing also applies in a switch with pattern matching. If you want to define a case for matching the type of a record field without the need to extract the value, you can write _ after the type.

For example, we have the following record and classes.

  record Box(Item item) {}

  sealed abstract class Item {}
  final class RedItem extends Item {}
  final class GreenItem extends Item {}
  final class BlueItem extends Item {}
  final class PinkItem extends Item {}

Below are the examples of how to define unnamed patterns.

  int size = 10;
  Box box = new Box(new RedBall());
  switch (box) {
    case Box(RedBall _), Box(GreenBall _), Box(BlueBall _) when size >= 10 ->   System.out.println("Primary color with big size");
    case Box(RedBall _), Box(GreenBall _), Box(BlueBall _) -> System.out.println("Primary  color with small size");
    case Box(_) -> System.out.println("Non-primary color");
  }

Summary

In this tutorial, we have learned how to use unnamed variables and patterns in Java. Instead of defining unnecessary names that will not be used, it's recommended to use unnamed variables and patterns if possible.

This feature requires Java 21 or above. If it's still a preview feature in the Java version that you use, you have to add --enable-preview flag when running the code.

You can also read about: