Skip to content

Declaring lambda parameters

โ˜• Java 17 ยท How Lambdas See the Variables Around Them ยท 1/4

Parameters are the values a lambda receives when it runs. You can declare them in three ways.

Three styles

Predicate<Movie> a = m -> m.isAvailable();          // no type
Predicate<Movie> b = (var m) -> m.isAvailable();    // var
Predicate<Movie> c = (Movie m) -> m.isAvailable();  // real type

Predicate<Movie> d = var m -> m.isAvailable();      // โŒ does not compile

All three valid lines do the same thing. The difference is the parentheses:

  • No type: with exactly one parameter, the parentheses are optional.
  • var: Java infers the type, but the parentheses become mandatory.
  • Real type: the parentheses are mandatory, and the type must match what the interface expects.

Parentheses can disappear only for a single parameter with no type at all.

Where the type comes from

With no type or var, Java reads the type from the context, the place where the lambda is used:

Predicate<User> adult = u -> u.age() >= 18;          // the variable: u is a User

void watch(Consumer<Episode> c, Episode e) { c.accept(e); }
watch((var ep) -> ep.play(), pilot);                 // the method: ep is an Episode

void sort(List<String> titles) {
    titles.sort((var a, var b) -> a.compareTo(b));   // the list: a and b are Strings
}

To find a parameter's type, ask: what is this lambda assigned to, or passed to?

One style per lambda

All the parameters of one lambda use the same style:

โŒ Mixed โœ… Consistent
(var t, r) -> t.isEmpty() (t, r) -> t.isEmpty()
(var t, String r) -> true (var t, var r) -> true
(String t, var r, Integer s) -> 1 (String t, String r, Integer s) -> 1
(Integer s, e) -> "Pilot" (Integer s, Integer e) -> "Pilot"

To fix a mixed list, add var or a type to every parameter, or remove it from all of them. var and real types can't be combined either.

final and annotations

Like method parameters, lambda parameters accept modifiers:

Consumer<Episode> c1 = (final var e) -> e.play();
Consumer<Episode> c2 = (@Deprecated Episode e) -> e.play();
titles.sort((final var a, @Deprecated var b) -> a.compareTo(b));

Consumer<Episode> c3 = (final e) -> e.play();        // โŒ does not compile

final stops the parameter from being reassigned in the body. A modifier needs something to attach to: var or a real type. You'll rarely need this in real code.

Parameters are what the lambda receives. Next: what it creates inside its own body.

๐Ÿ’ป Code: Java17_Part_8_Functional_Programming on GitHub

Next: variables inside the block โ†’