Why is the “Variable used in Lambda expression must be final or effectively final” warning ignored for instance variables [duplicate]

大城市里の小女人 提交于 2020-01-21 03:45:08

问题


I'm studying java 8 streams and the only problem I have is understanding lambdas is why the effectively final warning in lambdas is ignored for instance(and static) variables. I can't seem to find any reference to it online, as most pages will just talk about the definition of being "effectively final".

public class LambdaTest {

    int instanceCounter = 0;

    public void method() {
        int localCounter = 0;
        instanceCounter = 5; //Re-assign instance counter so it is no longer effectively final

        Stream.of(1,2,3).forEach(elem -> instanceCounter++); //WHY DOES THE COMPILER NOT COMPLAIN HERE
        Stream.of(1,2,3).forEach(elem -> localCounter++); //Does not compile because localCounter is not effectively final
    }
}

回答1:


We tend to forget that instanceCounter is actually this.instanceCounter, you are capturing this which is well, effectively final. As to why this is needed, the answer is obviously here




回答2:


Why the compilation error for local variables?

The effectively final rule only applies to local variables and not global variables and for that reason, there is no compilation error for the first scenario as you're mutating a global variable.

If it helps capturing an instance variable can be seen as capturing the final local variable this so there is no compilation error.

Why is there such a restriction?

The book Java-8 in Action has a valid explanation for this restriction, it goes as follows:

You may be asking yourself why local variables have these restrictions. First, there’s a key difference in how instance and local variables are implemented behind the scenes. Instance variables are stored on the heap, whereas local variables live on the stack. If a lambda could access the local variable directly and the lambda were used in a thread, then the thread using the lambda could try to access the variable after the thread that allocated the variable had deallocated it. Hence, Java implements access to a free local variable as access to a copy of it rather than access to the original variable.

This makes no difference if the local variable is assigned to only once hence the restriction. Second, this restriction also discourages typical imperative programming patterns that mutate an outer variable.



来源:https://stackoverflow.com/questions/47998733/why-is-the-variable-used-in-lambda-expression-must-be-final-or-effectively-fina

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!