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