你可能在安卓中編寫過如下程序,在內部類中試圖捕獲局部變量。但在Java1.8之前是不允許這樣捕獲的。
如果你非要捕獲可變變量,可以使用下面兩種技巧中的一個:
1. 聲明一個單元素數組,其中儲存可變值
2. 創建一個包裝類的實例,存儲要改變的值的引用。
思考: Java爲什麼要這麼要求呢?
總的來說,爲了保證內部類得到的局部變量的數據是一致的。假如上圖代碼中 變量out 在打印後修改,然後再次在外部打印out,這回造成不一致! 所以final是保證一致性。在Java1.8之後IDEA對此進行優化 默認對局部變量設置爲final。
在Kotlin中,如若捕獲可變值可以如下處理:
class Ref<T>(var value:T)
val counter = Ref(0)
val inc = { counter.value++ }
在實際代碼中 可以直接如此編寫:
var counter = 0;
val inc = {counter++}
原理是捕捉了一個val變量,他的值被copy下來,和Java一樣,當捕獲var值時,他被當成一個類的字段儲存下來,該類的引用會是final的。
但是,在事件處理器或者監聽時,捕獲局部變量並修改只會在監聽時發生,該聲明內部類的方法一結束,但內部類生命週期並未終止,所以,對局部變量的修改只會在監聽時生效!
如下並不是記錄點擊按鈕的正確操作:
fun tryToCountButtonClicks(button:Button):Int{
var clicks = 0
button.onClick{ clicks++ }
return clicks //clicks始終返回0! 所以存儲到成員變量較合適
}
參考 xiancaieeee https://blog.csdn.net/xiancaieeee/article/details/8834352