我在Java 8中使用lambda,我遇到警告,从lambda表达式引用的局部变量必须是final或有效的final。我知道当我在匿名类中使用变量时,它们在外部类中必须是final,但final和有效final之间的区别是什么?


当前回答

如果可以将最后一个修饰符添加到局部变量,那么就是 有效的决赛。

Lambda表达式可以访问

静态变量, 实例变量, 有效的最终 方法参数,以及 有效的最终 局部变量。

来源:OCP: Oracle认证专业Java SE 8程序员II学习指南,Jeanne Boyarsky, Scott Selikoff

此外,

有效最终变量是一个值为never的变量 更改了,但没有使用final关键字声明。

来源:从Java开始:从控制结构到对象(第6版),Tony Gaddis

此外,不要忘记final的含义,它在第一次使用之前只初始化一次。

其他回答

public class LambdaScopeTest {
    public int x = 0;        
    class FirstLevel {
        public int x = 1;    
        void methodInFirstLevel(int x) {

            // The following statement causes the compiler to generate
            // the error "local variables referenced from a lambda expression
            // must be final or effectively final" in statement A:
            //
            // x = 99; 

        }
    }    
}

正如其他人所说,在初始化后值从未改变的变量或参数实际上是final的。在上面的代码中,如果你在内部类FirstLevel中改变了x的值,那么编译器会给你一个错误消息:

从lambda表达式引用的局部变量必须是final或有效final。

如果可以将最后一个修饰符添加到局部变量,那么就是 有效的决赛。

Lambda表达式可以访问

静态变量, 实例变量, 有效的最终 方法参数,以及 有效的最终 局部变量。

来源:OCP: Oracle认证专业Java SE 8程序员II学习指南,Jeanne Boyarsky, Scott Selikoff

此外,

有效最终变量是一个值为never的变量 更改了,但没有使用final关键字声明。

来源:从Java开始:从控制结构到对象(第6版),Tony Gaddis

此外,不要忘记final的含义,它在第一次使用之前只初始化一次。

' effective final'是一个变量,如果它被'final'附加,则不会产生编译器错误

在“Brian Goetz”的一篇文章中,

非正式地说,如果局部变量的初始值从未改变,那么它实际上就是final变量——换句话说,声明它为final不会导致编译失败。

lambda-state-final- Brian Goetz

我发现解释“有效的final”最简单的方法是想象在变量声明中添加final修饰符。如果通过这个更改,程序在编译时和运行时继续以相同的方式运行,那么该变量实际上就是final。

effective final变量是一个局部变量,即:

未定义为最终 只分配一次。

final变量是这样的变量:

用final关键字声明。