Card 07/ 09

GotchaDifficulty: Advanced1 min

Why Your Lambda Cannot Change That Variable

A counter incremented inside a forEach. The compiler refuses the line, with a message about a variable being final when nothing in the source says final.

java
int total = 0;
invoices.forEach(invoice -> total += invoice.pence());
text
Report.java:2: error: local variables referenced from a lambda expression must be final or effectively final

A lambda captures a copy of the local variables it uses, because the method that declared them may have returned long before the lambda runs. Allowing the lambda to assign to its copy would look like changing the original and would not be.

So the compiler insists that captured locals never change at all — declared final, or never assigned to after their first value, which is what "effectively final" means.

The real answer is that summing in a forEach is the wrong shape. Let the pipeline produce the value rather than accumulating into something outside it.

java
long total = invoices.stream().mapToLong(Invoice::pence).sum();