You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lambda表达式中变量为何必须是final或有效final?

Why Lambdas Require Final or Effectively Final Variables

First, let's look at your code example that triggers the compile error:

public class test { 
    public static void main(String[] args) throws ExecutionException, InterruptedException { 
        ExecutorService executorService = Executors.newFixedThreadPool(10); 
        List<Future<String>> futureLists = new ArrayList<>(); 
        for (int i = 0; i < 20; i++) { 
            futureLists.add(executorService.submit( () -> "Hello world" + i)); 
        } 
        for (Future<String> itr:futureLists) { 
            System.out.println(itr.get()); 
        } 
    } 
}

You know removing i fixes the issue, but let's break down why Java enforces this rule for lambdas:

  • Avoid unpredictable results in concurrent code: Lambdas are frequently used in async/parallel scenarios (like your ExecutorService example), where the lambda might run long after the surrounding code has moved on. If non-final variables were allowed, their values could change before the lambda executes. In your loop, i increments every iteration—if the lambda could access it directly, by the time the thread runs, i might already be 20 (or some other unexpected value), leading to inconsistent outputs.

  • Maintain consistency with anonymous inner classes: Before lambdas arrived in Java 8, anonymous inner classes already required accessed local variables to be final or effectively final. This rule carries over to lambdas to keep the language consistent, so developers don't have to learn conflicting rules for similar functionality.

  • Simplify compiler logic and prevent race conditions: When a lambda captures a variable, the compiler needs to manage how that variable is accessed. If the variable is final or effectively final, the compiler can safely copy its value into the lambda's closure without worrying about future modifications. Allowing mutable variables would force the compiler to handle synchronization and memory visibility issues, adding unnecessary complexity and opening the door to hard-to-debug race conditions.

As an alternative fix besides removing i, you can capture a local effectively final copy of i inside the loop:

for (int i = 0; i < 20; i++) {
    int currentNum = i; // This is effectively final
    futureLists.add(executorService.submit(() -> "Hello world" + currentNum));
}

内容的提问来源于stack exchange,提问作者QuackDuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:03:24