Why must the variables a Java lambda captures be effectively final, and what does effectively final actually mean?
Effectively final means a variable is never reassigned after its initialisation. You do not have to declare it final — the compiler just checks that no assignment to it appears anywhere after the declaration.
The rule exists because a lambda does not run immediately. The lambda body may execute long after the enclosing method has returned, possibly on another thread, and by then the enclosing frame is gone. If the lambda could see a variable that had been reassigned, it would have no way to know which value it was supposed to use, and the result would depend on timing. The rule removes the ambiguity by guaranteeing that a captured variable always has the value it had when the lambda was created.
import java.util.function.Supplier;
public class Main {
public static void main(String[] args) {
int base = 10;
Supplier<Integer> supplier = () -> base + 5; // base is effectively final
System.out.println("supplier : " + supplier.get());
// Uncommenting the line below makes the lambda fail to compile:
// base = 20;
// The error says the local variable base must be final or effectively final.
}
}The output shows the working case. The lambda captures the int base, and because base is never reassigned the compiler is happy.
Notice what the rule does not say. It does not require the captured object to be immutable. If you capture a StringBuilder and mutate it inside the lambda, that is perfectly legal, because the rule is about reassigning the variable, not about changing the object. The same applies to a field — fields are not subject to the rule at all, since a lambda can read and write this.field freely.
The reason the rule covers only local variables and parameters is that those are the ones that live on the stack frame of the enclosing method. When the method returns, the frame is gone, and the only way for the lambda to keep using them is for the compiler to copy them into the lambda's own storage. That copy is only meaningful if the value does not change.