Java 10 introduced var for local variable type inference, which was a huge hit for reducing boilerplate. Java 11 takes this a step further by allowing the use of var for parameters in lambda expressions (JEP 323).
While it might seem minor, this feature brings consistency to the language and solves a specific problem related to annotations.
Evolution of Lambda Syntax
Let’s look at how lambda parameter syntax has evolved:
1. Implicit Types (Pre-Java 11)
The compiler infers the types automatically. This is the most concise.
(s1, s2) -> s1 + s2
2. Explicit Types (Pre-Java 11)
You manually specify the types. This is required if you want to use annotations.
(String s1, String s2) -> s1 + s2
3. Using var (Java 11)
You can now use var for lambda parameters.
(var s1, var s2) -> s1 + s2
Why Use var in Lambdas?
If the compiler can already infer the types (Scenario 1), why bother with var? The primary reason is annotations.
If you need to apply an annotation to a lambda parameter, you cannot do it with implicit types. Before Java 11, you had to write out the full type name:
// Before Java 11
( @Nonnull String s ) -> s.toUpperCase()
With Java 11, you can use var, keeping the code concise while still allowing the annotation:
// Java 11
( @Nonnull var s ) -> s.toUpperCase()
Simple Rules for Using var in Lambdas
To keep the syntax predictable, there are a few rules you must follow:
1. No Mixing
You cannot mix var with explicit types or implicit types in the same lambda.
(var x, y) -> ... // ERROR
(var x, String y) -> ... // ERROR
2. Must Use Parentheses
Even if there is only one parameter, you must use parentheses if you use var.
var x -> x.toLowerCase() // ERROR
(var x) -> x.toLowerCase() // OK
3. Use for Consistency
If your codebase uses var heavily for local variables, using var in lambdas makes your code style feel more unified.
Real-World Example: Secure Web Client
Imagine you are using a library where you need to mark lambda parameters as @Sensitive to ensure they are handled correctly by a security scanner.
// Clear and concise security marking
authService.login((@Sensitive var username, @Sensitive var password) -> {
return authenticate(username, password);
});
Conclusion
The addition of var to lambda parameters in Java 11 isn’t about saving a few keystrokes—it’s about consistency and enabling meta-programming features like annotations without sacrificing the benefits of type inference. It’s a small but meaningful refinement that makes the Java language feel more modern and well-rounded.