匿名內部類訪問final區域性變數

鴨脖發表於2015-04-20

舉一個最簡單的例子,拿Andorid開發來講,我們在一個函式中new了一個progressbar,然後我們給一個按鈕設定了OnClickListener,希望點選了這個按鈕之後,進度條消失。自然而然的,最簡單的方法,就是我們將progressbar設定為外部類的成員,這樣內部類和這個成員的生命週期就一致了,訪問當然也沒有問題。但是,如果不允許新增新的成員呢?

這個時候,通過設定該progressbar為final就可以解決問題了。這是為什麼呢?

我們都知道,在java中,全域性變數,final變數和static變數,都是儲存在heap中的;而區域性變數則是儲存在frame中的,函式呼叫的過程中,用ebp來指向棧底,而用esp來指向正在執行處。

而且函式內部呼叫其他函式的時候,會壓棧,push ebp,生成新的frame。要把上一個frame中的區域性變數傳遞給下一個frame,一般是使用相對位置來表示的,比如ebp-4等。

但是外部類中的區域性變數和內部類物件的生命週期是不一致的,這個時候,如果跨frame,那麼內部類中的frame就找不到外部類中的區域性變數的位置。

所以,就有了final機制。

這是一種copy local variable的設計。final型別的區域性變數在被匿名內部類訪問的時候,會自動被拷貝,該拷貝會變為內部類的成員,從而造成了一種區域性變數生命週期延長的假象。

最後需要說明一點的是,匿名內部類只能使用一次哦。

相關文章