schoolcoder
schoolcoder

Reputation: 1654

Why should variables inside a forEach loop not be changed?

I am iterating a list in Java 7 loop and Java 8 forEach loop. The Java 8 loop wants the variables inside it to not change. For example:

List<String> testList = Arrays.asList( "apple", "banana", "cat", "dog" );
int count = 0;

testList.forEach(test -> {
  count++; // Compilation error: Local variable count defined in an enclosing scope must be final or effectively final
});

for (String test : testList) {
  count++; // Code runs fine
}

Can someone explain why? Is it a drawback of Java 8?

Upvotes: 34

Views: 41933

Answers (1)

Tagir Valeev
Tagir Valeev

Reputation: 100209

The Java Memory Model has very important property: it guarantees that local variables and method parameters are never writable by another thread. This adds much safety to multi-threading programming. However when you create a lambda (or an anonymous class), nobody knows how it will be used. It can be passed to another thread for execution (for example, if you use parallelStream().forEach(...)). Were it possible to modify the local variable that important property would be violated. Not the thing the Java language developers would sacrifice.

Usually when you are using lambdas, you are trying to program in functional way. But in functional programming mutable variables are considered bad practice: it's better to assign every variable only once. So trying to modify the local variable actually smells. Use various stream reduction methods instead of forEach to produce a good functional code.

Upvotes: 59

Related Questions