浅析lambda表达式只能引用final修饰的变量
- 总结
下面lambda表达式
反编译的后的结果:
源码:
import java.util.function.Consumer;
public class LambdaTest {
Object instanceObj = new Object();
private void test() {
// 用于直接引用
Object localObj1 = new Object();
// 用于传参
Object localObj2 = new Object();
Consumer consumer = (x) -> {
System.out.println(x);
System.out.println(localObj1);
System.out.println(instanceObj);
};
consumer.accept(localObj2);
}
}
反编译:
javac src/LambdaTest.java
javap -p src/LambdaTest.class
输出:
Compiled from "LambdaTest.java"
public class LambdaTest {
java.lang.Object instanceObj;
public LambdaTest();
private void test();
private void lambda$test$0(java.lang.Object, java.lang.Object);
}
lombda表达式变成了一个私有方法,且默认一个形参,变成了两个形参。
多的那个形参传的自然就是final
关键字修饰的变量。
然后,我们想一想传统的方法
,无论实参传递的是基本数据类型还是复杂数据类型,形参都会拷贝一份数据/地址
,我们修改形参绝不会影响到实参。但是我们写lambda表达式修改变量,很直观的感受就像似直接修改了实际数据。给人一种误会,java为了避免这种误会,将所有匿名内部内、lombda表达式引用的变量默认都会标记成final
不可变。
引用原作者的关键语句:为了避免这种误导混淆,保证局部变量和Lambda的变量副本的数据一致性,Java直接在语法层面强制Lambda表达式引用的局部变量不可被重新赋值。