考虑Lambda Expressions中给出的以下代码:
import java.util.function.Consumer;
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;
Consumer<Integer> myConsumer = (y) ->
{
System.out.println("x = " + x); // Statement A
System.out.println("y = " + y);
System.out.println("this.x = " + this.x);
System.out.println("LambdaScopeTest.this.x = " +
LambdaScopeTest.this.x);
};
myConsumer.accept(x);
}
}
public static void main(String... args) {
LambdaScopeTest st = new LambdaScopeTest();
LambdaScopeTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
在JavaDocs中写道:
假设您立即添加以下赋值语句 在
methodInFirstLevel
定义声明之后:void methodInFirstLevel(int x) { x = 99; // ... }
由于此赋值语句,变量
FirstLevel.x
不再是有效的最终结果。结果,Java 编译器生成类似于&#34;局部变量的错误消息 从lambda表达式引用必须是最终的或有效的 最终&#34; lambda表达式myConsumer尝试访问的位置FirstLevel.x
变量:
System.out.println("x = " + x);
我无法理解在System.out.println("x = " + x)
(声明A)如何访问FirstLevel.x?不应该是方法x
中传递的methodInFirstLevel(int x)
吗?
答案 0 :(得分:2)
这似乎是本教程中的错误。我认为该段应该是:
由于此赋值语句,参数
x
不是 有效地终结了。结果,Java编译器生成了一个 类似于“从lambda引用的局部变量的错误消息 表达必须是最终的或有效的最终“lambda 表达式myConsumer尝试访问x
参数:System.out.println("x = " + x);
我将我的论点放在两个观察上:引用的错误消息表示“局部变量”,可能包括参数,但不包括字段。引用的print语句打印23,这是参数的值,而不是FirstLevel.x
的值。
答案 1 :(得分:0)
始终:如果方法中有任何局部变量,那么Java将首先选择局部变量,然后类原因是局部变量的范围非常有限,类变量可以在类的所有方法中访问
答案 2 :(得分:0)
Java始终使用具有给定名称的最内层变量。
导致此层次结构(降序):
除非您使用this.var
或Class.var
明确限定。