How can a Lambda expression access variables outside its scope? What is the concept behind it?

A lambda expression can read local variables from its enclosing scope through a mechanism called variable capture, but only if those variables are final or effectively final, meaning their value is never changed after initialization.

Key Points: • Java captures local variables by value at the time the lambda is created, storing a copy rather than a live reference to the variable. • The final/effectively-final restriction guarantees that the captured copy always matches what the variable would have held, since it can never change afterward. • Instance and static fields are not subject to this restriction, because they're accessed through the enclosing object or class, not copied by value — a lambda can freely read and write them. • This design keeps lambdas safe to execute later or on a different thread than where they were created, without the risk of the captured variable changing underneath them. • Attempting to modify a captured local variable inside or outside the lambda after it's used causes a compile-time error, not a runtime one.

Example: In int threshold = 10; list.stream().filter(x -> x > threshold).collect(...), the lambda captures threshold's value (10) at creation time; if threshold were reassigned anywhere afterward, the code wouldn't even compile.

Code Example:

int threshold = 10;

List<Integer> nums = Arrays.asList(5, 12, 8, 20);

List<Integer> aboveThreshold = nums.stream()
        .filter(n -> n > threshold)
        .collect(Collectors.toList());

Interview Tip: A concise interview answer is:

"A lambda can read local variables from its enclosing scope, but only if they're final or effectively final, because Java captures them by value as a snapshot at creation time. That restriction exists so the lambda behaves predictably even if it runs later or on another thread — instance and static fields don't have this limitation since they're accessed through the object or class instead of being copied."