Open In App

Lambda Expression Variable Capturing with Examples

Last Updated : 25 Oct, 2025
Comments
Improve
Suggest changes
5 Likes
Like
Report

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();
    }
}

Output
Instance 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();
    }
}

Output
Counter: 6

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();
    }
}

Output
Local 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);
    }
}

Output
Value: 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.



Article Tags :

Explore