Lambda Expression Variable Capturing with Examples
Last Updated :
25 Oct, 2025
When we write a lambda expression in Java, it can access variables that are defined outside its own block, such as variables from the surrounding method or class. This process is called variable capturing. However, there are a few important rules about which variables can be used and how they can be modified.
Types of Variables Captured in Lambdas
Lambda expressions can capture three types of variables from their enclosing scope:
1. Capturing Instance Variables
A lambda can directly access instance variables of its enclosing class.
Java
class GFG{
private int number = 10;
void display(){
Runnable r = () -> {
System.out.println("Instance variable: " + number);
};
r.run();
}
public static void main(String[] args){
new GFG().display();
}
}
OutputInstance variable: 10
Explanation: The lambda expression captures the instance variable number from the current object using this.number. It can modify it if not declared final.
2. Capturing Static Variables
Static variables belong to the class rather than any instance, and Lambda Expression can access and modify them freely.
Java
class GFG{
private static int counter = 5;
void increment(){
Runnable r = () -> {
counter++;
System.out.println("Counter: " + counter);
};
r.run();
}
public static void main(String[] args){
new GFG().increment();
}
}
Explanation: The lambda directly modifies the static variable counter, since it is shared across all instances of the class.
3. Capturing Local Variables
Lambda Expression can capture local variables declared in the enclosing method. However, these variables must be effectively final — meaning they are not modified after being assigned.
Java
class GFG{
void show(){
int num = 20;
Runnable r = () ->{
System.out.println("Local variable captured: " + num);
};
r.run();
}
public static void main(String[] args){
new GFG().show();
}
}
OutputLocal variable captured: 20
Explanation: The variable num is captured by the lambda. Since it is not modified anywhere after initialization, it is considered effectively final.
Why Lambdas Require Final or Effectively Final Variables
Lambda expression can outlive their defining method. To ensure consistency, they can capture only local variables that are final or effectively final, guaranteeing predictable, unchanging values.
Java
import java.util.*;
public class GFG{
public static void main(String[] args){
List<Runnable> tasks = new ArrayList<>();
for (int i = 0; i < 3; i++){
// Effectively final variable
int temp = i;
tasks.add(
() -> System.out.println("Value: " + temp));
}
tasks.forEach(Runnable::run);
}
}
OutputValue: 0
Value: 1
Value: 2
Explanation: Each lambda captures a different copy of the variable temp (which is effectively final).
If we used i directly without creating a separate variable, it would cause a compile-time error because i changes in each loop iteration.
Explore
Java Basics
OOP & Interfaces
Collections
Exception Handling
Java Advanced
Practice Java