This question already has an answer here:
When I am writing this code I am getting a compile time error which says: 'Variables in lambdas must be final or effectively final'.
Now, I get this that removing the i from the line :
futureLists.add(executorService.submit( () -> "Hello world" + i));
solves the issue.
But I want to know that why does such a requirement exist?
As per the JLS, all it says is :
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final, or a compile-time error occurs where the use is attempted.
But it does not state, why such a requirement exist. But why did Java engineers enforce such a requirement for lambdas?
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());
}
}
}
It is related to multi-thread programming.
Immutable things are easy to distribute. Multiple consumers can use them without having to worry about someone else might have changed the value. Lambda functions in Java are taking Java in the realm of functional programming where you can pass the function around. This is very useful in distributed programming. Since there can be multiple processors it is better to pass final values than adding overhead of concurrency management.
The likely reason the Java engineers did this, was to make Java code more durable. When one would allow the variable to be non-final, it's value could be modified from virtually anywhere in the program. This could potentially cause concurrency problems.
It is mentioned in this document: