为什么lamda不能修改外部引用的变量?
生活随笔
收集整理的這篇文章主要介紹了
为什么lamda不能修改外部引用的变量?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- lamda表達式實際上一個匿名內部類
- 所以我們的問題可以轉向這兩個問題:
- 為什么匿名內部類調用外部引用的時候,外部引用需要用final修飾?
- lamda如果才能修改外部引用變量?
1. 為什么匿名內部類調用外部引用的時候,外部引用需要用final修飾?
- 我們在內部類中調用外部的自由變量,即使該變量沒有顯式的聲明final,但是在編譯器解析的時候也被定義成一個final變量
- 這里java內部類引用外部變量近似閉包的概念。我們先來了解一下js中滿足閉包的條件:
- 一個依賴于外部環境自由變量的函數
- 這個函數能夠訪問外部環境里的自由變量
- 閉包常見使用場景
- 回調函數
- 匿名函數
- 在閉包中訪問外部自由變量訪問的是自由變量的哪個值呢?
- 是閉包定義時,自由變量所定義的值(非運行時!)
- js中通常我們要解決閉包導致對象不正確問題,常用的有四個解決方案:
- func.call(obj, 20, 30)
- func.apply(obj, [20,30])
- const func1 = func.bind(obj,20,30)
- 在閉包外方法中手動指定 let self = this
- 說到閉包,繞不開this指向問題,this應該指向的是運行時的對象,簡單總結this指向三種情況:
- obj.func() -> this指向.前面調用的對象,此時指向obj
- new Fun() -> this指向new出來的對象
- 函數自調、匿名函數和回調函數 -> this指向的是window
- java對閉包的處理
- 如函數在使用類的全局變量的時候
- 全局變量實際是類的一個屬性,用this指向,可所以修改
- 但是在處理匿名內部類的時候,在不同的類中無法用this指向,這時java的做法是:
- 將自由變量拷貝一個副本帶給匿名內部類,供內部類使用。
- 類似于值傳遞而非引用傳遞
2. lamda如果才能修改外部引用變量?
3. 劃重點
lamda不能修改外部引用的變量的原因其實也很簡單,本質上就是因為lambda表達式在方法內部,那么lambda表達式的內存分配就是在棧上。棧內存不存在線程安全問題,因為棧內存存的都是變量的副本。 對于局部變量count而言,它的生命周期就是所在方法的生命周期。這就決定了count無法被位于同一個棧幀上的lambda修改,因為這種修改毫無意義, 你無法將你的修改傳遞出當前棧幀。棧內存不會被共享,也就意味著你沒有權利和其他棧幀通信。如果非要在lambda內部修改lambda表達式外部的局部變量的值呢? 有兩種方式:使用數組或者把局部變量定義為全局變量。這2種方式,其實本質是一樣的:內存都分配在堆上。這就決定了,使用這2種方式來修改變量的值,是可行的。轉載請注明出處:www.meidanlong 😃
總結
以上是生活随笔為你收集整理的为什么lamda不能修改外部引用的变量?的全部內容,希望文章能夠幫你解決所遇到的問題。