Memra

Lambda syntax & effectively-final capture

Writing lambdas in all their forms — and the capture rule that trips up the exam.

Lambdas: code as a value

A lambda is an anonymous function you can pass around as a value. It implements a functional interface — an interface with exactly one abstract method. The compiler figures out which method by looking at the target type.

The three syntax forms:

// 1 — multi-param, expression body
BinaryOperator<Integer> add = (a, b) -> a + b;

// 2 — single param: parentheses optional
Predicate<String> empty = s -> s.isEmpty();

// 3 — block body with an explicit return
Function<Integer, String> describe = n -> {
    if (n > 0) return "positive";
    if (n < 0) return "negative";
    return "zero";
};

Type annotations on parameters are optional when the compiler can infer them from context — and it usually can.

Variable capture: a lambda can read local variables from its enclosing scope, but only if those variables are effectively final — never reassigned after their first assignment. The rule applies to both final variables and variables that *could* have been declared final:

int threshold = 5;          // effectively final — never reassigned
Predicate<Integer> big = n -> n > threshold;  // OK

int mutable = 5;
mutable = 6;                // not effectively final
Predicate<Integer> bad = n -> n > mutable;    // COMPILE ERROR

Lambdas can freely access this and instance fields of the enclosing class — only local variables are subject to the effectively-final rule.

NORMAL ~/memra/learn/java-from-zero/lambda-syntax utf-8 LF