被匿名內部類引用的變量會被拷貝一份到內部類的環境中
但其后,在外部,該變量如果被修改,則內部外部不一致
Java為了避免數據不同步的問題,做出了匿名內部類只可以訪問final的局部變量的限制。
究其原因,在於 區域變量 x 並不是真正被拿來於內部匿名類別中使用,而是在內部匿名類別中復制一份,作為field成員來使用,由於是復本,即便您在內部匿名類別中對 x 作了修改,會不會影響真正的區域變量 x,事實上您也通不過編譯器的檢查,因為編譯器要求您加上"final"關鍵詞,這樣您就知道您不能在內部匿名類別中改變 x 的值。
總結下來就是:
- Java設計者想要匿名函數或者Lambda函數內部外部保持數據一致性(知道了目的才好理解)
- 然而Java只是實現了capture-by-value形式的閉包,也就是匿名函數內部會重新拷貝一份自由變量(參考答案中閉包的概念),然后函數外部和函數內部就有兩份數據
- 那么要想實現1中的目的,只能要求兩處變量不變。JDK8之前要求使用final修飾,JDK8聰明些了,可以使用effectively final的方式。java8里不用final修飾局部變量也可以編譯通過。總之,兩邊不變就行了。
https://www.zhihu.com/question/21395848