Java 中使用 Lambda 为什么只能使用 final 变量?


  • Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。
  • Lambda 表达式免去了使用匿名方法的麻烦,并且给予 Java 简单但是强大的函数化的编程能力。

Lambda 原理

很多人提到 Lambda 的原因,就直接说 Lambda 是靠匿名内部类实现的。这个说法不完全准确。

Lambda 表达式,有可能会生成内部类;也有可能会生成私有静态方法,还有可能生成私有方法。

具体是哪种形式,和你使用的函数式编程有关。

关于这个原理,我认为可以单独拿一篇文章来说,今天不过多讨论。

Lambda 变量作用域

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。



 

 

上面代码中有一个 num 变量,并没有标记为 final。但是它却被 Lambda 表达式使用了。所以,是你说的不对?

我说的并没有错,原因是,在 Java 中:如果我声明了一个变量,且在后面不更改它的值,那么那就是事实上的 final。这种变量在 lambda 是可以使用的,但是不能被修改。

如果我们尝试修改 num 变量,发现不被允许。


 

 如果我们不在 Lambda 中修改它,而只在 Lambda 中使用它。然后,在 Lambda 外部修改它,可能会有并发问题。正常情况下是允许的,但是在线程中是不被允许的。

我们都知道实例变量是储存在堆上面的,是线程贡献的。而局部变量则是保存在栈上的,是线程不共享的。

java 访问局部变量的时候,实际上是去访问他的副本。如果局部变量改变了,那访问的也是之前的值。尤其是当 Lambda 是在一个线程中使用变量的,造成的数据不同步问题更加明显,因此 Lambda 有了 final 限制。

在 Java 中方法调用是值传递的,所以在 lambda 表达式中对变量的操作都是基于原变量的副本,不会影响到原变量的值。

综上,假定没有要求 lambda 表达式外部变量为 final 修饰,那么开发者会误以为外部变量的值能够在 lambda 表达式中被改变,而这实际是不可能的,所以要求外部变量为 final 是在编译期以强制手段确保用户不会在 lambda 表达式中做修改原变量值的操作。

另外,对 lambda 表达式的支持是拥抱函数式编程,而函数式编程本身不应为函数引入状态的,从这个角度看,外部变量为 final 也一定程度迎合了这一特点。



说白,lamda就是内部类的简写,调用外部类变量,必须是final类型的。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM