Java_lambda中引用的局部变量为什么必须为final类型

Source

lambda表达式中调用局部变量,需要满足两个条件

1.局部变量类型为final
2.局部变量类型为effectively final

关于effectively final:即实际上的final,这是Java1.8版本中的新特性,编译器会尝试给局部变量加上final关键字,若变量在此之前未被修改则可成功;相对应的,在Java1.7及以前的版本,必须显示地为局部变量添加final关键字

局部变量必须为final类型的原因

分两步说明:生命周期与数据一致性

1.生命周期

lambda表达式本质上是一种简写的匿名内部类,类的对象存储于堆,对象的生命周期止于GC;而局部变量的生命周期与定义该变量的方法同步,从入栈开始,至出栈结束

此时可能会产生一个问题:方法结束,栈帧出栈,局部变量生命周期结束,但对象尚未被GC,若此时对象调用局部变量,将无法调用;此为生命周期不同步引起的问题

Java为了应对这种情况,存在一种机制:若内部类引用了局部变量,则会在内部类中创建该局部变量的副本,如此一来局部变量就"成为"了内部类的成员变量,生命周期与内部类对象同步

2.数据一致性

内部类创建的副本并不会随着局部变量的改变而改变,所以一旦局部变量发生改变,就会产生数据不一致的问题

所以需要局部变量为final类型或effectively final类型,以保证数据的一致性