How to Use var in Lambda Expressions in Java

Introduction

Java 11 introduced the ability to use the var keyword in lambda expressions. This feature provides a way to define lambda parameters without explicitly specifying the parameter types, while still allowing the compiler to infer the types based on context. It can also be useful when you want to add annotations or modifiers to lambda parameters.

In this guide, we'll explore how to use var in lambda expressions, including basic usage, the ability to annotate lambda parameters, and the constraints that come with it.

Program Steps

  1. Create a Lambda Expression Without var: Start by using a lambda expression with explicit parameter types.
  2. Convert Lambda Expression to Use var: Replace the explicit parameter types with var and observe how the compiler infers the types.
  3. Annotate Lambda Parameters Using var: Add annotations to lambda parameters, which is possible when using var.
  4. Test Multiple Parameters with var: Use var with lambda expressions that have more than one parameter.
  5. Understand var Rules in Lambda Expressions: Learn the constraints when using var in lambda expressions.

Example 1: Lambda Expression Without var

import java.util.List;

public class LambdaWithoutVar {
    public static void main(String[] args) {
        List<String> names = List.of("Ravi", "Amit", "Pooja");

        // Step 1: Using lambda expression without var
        names.forEach((String name) -> System.out.println(name));
    }
}

Output

Ravi
Amit
Pooja

Explanation

  • We use a lambda expression that explicitly declares the parameter type as String. This is the traditional way to define lambda expressions when the parameter type is known.
names.forEach((String name) -> System.out.println(name));

In this case, name is explicitly declared as a String.


Example 2: Using var in Lambda Expression

import java.util.List;

public class LambdaWithVar {
    public static void main(String[] args) {
        List<String> names = List.of("Ravi", "Amit", "Pooja");

        // Step 2: Using var in the lambda expression
        names.forEach((var name) -> System.out.println(name));
    }
}

Output

Ravi
Amit
Pooja

Explanation

  • In this step, we replace the explicit type (String) with var. The var keyword allows the compiler to infer the type of name, which in this case is String, based on the context of the list.
names.forEach((var name) -> System.out.println(name));

The type inference works because the List<String> is defined as a list of strings.


Example 3: Using var with Annotations in Lambda Expressions

import java.util.List;

public class LambdaWithVarAnnotations {
    public static void main(String[] args) {
        List<String> names = List.of("Ravi", "Amit", "Pooja");

        // Step 3: Using var with annotations in the lambda expression
        names.forEach((@Deprecated var name) -> System.out.println(name));
    }
}

Output

Ravi
Amit
Pooja

Explanation

  • One advantage of using var is that it allows you to apply annotations to lambda parameters. In this example, we use the @Deprecated annotation with the lambda parameter name:
names.forEach((@Deprecated var name) -> System.out.println(name));

Without var, you would need to explicitly specify the type if you wanted to apply annotations. Using var makes this simpler.


Example 4: Using var with Multiple Parameters

import java.util.Map;

public class LambdaWithVarMultipleParams {
    public static void main(String[] args) {
        Map<Integer, String> numberMap = Map.of(1, "One", 2, "Two", 3, "Three");

        // Step 4: Using var in lambda expression with multiple parameters
        numberMap.forEach((var key, var value) -> System.out.println(key + " = " + value));
    }
}

Output

1 = One
2 = Two
3 = Three

Explanation

  • When you have multiple parameters in a lambda expression, you can use var for both parameters:
numberMap.forEach((var key, var value) -> System.out.println(key + " = " + value));

However, if you use var for one parameter, you must use var for all parameters. For example, this is invalid:

(numberMap.forEach((var key, value) -> System.out.println(key + " = " + value))); // Invalid

You must use var consistently across all parameters in a lambda expression.


Example 5: Understanding the Rules for var in Lambda Expressions

import java.util.List;

public class LambdaWithVarRules {
    public static void main(String[] args) {
        List<String> names = List.of("Ravi", "Amit", "Pooja");

        // Valid usage of var
        names.forEach((var name) -> System.out.println(name));

        // Invalid: mixing var and no var in the same lambda expression
        // names.forEach((var name, age) -> System.out.println(name));  // Compilation error
    }
}

Explanation

  • There are specific rules when using var in lambda expressions:

    • Consistency: If you use var for one parameter, you must use it for all parameters in that lambda expression.

    • No Mixing: You cannot mix var and implicit type inference. For example, the following is invalid:

    (var name, age) -> System.out.println(name);  // Invalid
    

    Instead, both parameters should either have var or neither should.


Conclusion

The introduction of var in lambda expressions in Java 11 adds flexibility and improves readability by reducing boilerplate code. You can now let the compiler infer the types of lambda parameters while also being able to apply annotations. However, there are strict rules you must follow when using var in lambda expressions. If you're working with multiple parameters, ensure that var is used consistently across all parameters. This feature simplifies the syntax while maintaining type safety and functionality.

Comments