lambda表达式原理:
Lambda 表达式引用的局部变量必须是最终变量或实际上的最终变量,也就是说局部变量在被创建后不得被重新赋值。
Lambda表达式是一个语法糖,会被编译生成为当前类的一个私有方法,Lambda表达式内直接引用局部变量本质是一种隐式传参,编译时会自动将引用的局部变量放到参数列表中(Lambda方法多了个参数),而引用的实例变量并不需要放到参数列表,因为方法内可以直接引用。
那么造成直接引用的局部变量需要final修饰的原因应该和这种隐式传参有关,所以这里需要再提一下Java方法的传参机制,详见之前发过的Java对象空间占用如何计算?
Java中引用数据类型是由引用变量和指向的实际对象两部分组成的。在方法传参时,本质上是将实际对象的内存地址赋值给方法参数中的引用变量**
所以在Lambda中对参数重新赋值或者在方法中将局部变量重新赋值,对另一方都是没有影响的。
结论
因此,为了避免这种误导混淆,保证局部变量和Lambda的变量副本的数据一致性,Java直接在语法层面强制Lambda表达式引用的局部变量不可被重新赋值。