標籤:
為什麼匿名內部類參數必須為final類型:
1) 從程式設計語言的理論上:局部內部類(即:定義在方法中的內部類),由於本身就是在方法內部(可出現在形式參數定義處或者方法體處),因而存取方法中的局部變數(形式參數或局部變數)是天經地義的,是很自然的。
2) 為什麼JAVA中要加上一條限制:只能訪問final型的局部變數?
JAVA語言的編譯器的設計者當然全實現:局部內部類能存取方法中的所有的局部變數(因為:從理論上這是很自然的要求),但是:編譯技術是無法實現的或代價極高.
至於為什麼只能是final,而不是staic,雖然二者從範圍上理解都應該可以被內部類訪問,但是sun公司可能考慮到更多的是安全性,因為static類型的變數會被內部類永久性改變,這個是不可取的。
3) 困難在何處?到底難在哪兒?
局部變數的生命週期與局部內部類的對象的生命週期的不一致性!
e.g1:
設方法 f 被調用,從而在它的調用棧中產生了變數 i , 此時產生了一個局部內部類對象 inner_object , 它訪問了該局部變數i .當方法f()運行結束後 , 局部變數 i 就已死亡了 , 不存在了. 但是:局部內部類對象 inner_object 還可能一直存在(只能沒有人再引用該對象時,它才會死亡),它不會隨著方法f()運行結束死亡。 這時:出現了一個"荒唐"結果: 局部內部類對象 inner_object 要訪問一個已不存在的局部變數 i !
e.g2 :
如何才能實現? 當變數是 final 時, 通過將 final 局部變數"複製"一份,複製品直接作為局部內部中的資料成員. 這樣: 當局部內部類訪問局部變數時,其實真正訪問的是這個局部變數的 "複製品"(即:這個複製品就代表了那個局部變數). 因此: 當運行棧中的真正的局部變數死亡時,局部內部類對象仍可以訪問局部變數(其實訪問的是"複製品" ),給人的感覺:好像是局部變數的"生命期"延長了.
總結:
核心的問題是:怎麼才能使得:訪問"複製品"與訪問真正的原始的局部變數,其語義效果是一樣的呢?
當變數是final時,若是基礎資料型別 (Elementary Data Type),由於其值不變,因而:其複製品與原始的量是一樣.語義效果相同.(若:不是final,就無法保證:複製品與原始變數保持一致了,因為:在方法中改的是原始變數,而局部內部類中改的是複製品)
當變數是final時,若是參考型別,由於其引用值不變(即:永遠指向同一個對象),因而:其複製品與原始的引用變數一樣,永遠指向同一個對象(由於是final,從而保證:只能指向這個對象,再不能指向其它對象),達到:局部內部類中訪問的複製品與方法代碼中訪問的原始對象,永遠都是同一個即:語義效果是一樣的.否則:當方法中改原始變數,而局部內部類中改複製品時,就無法保證:複製品與原始變數保持一致了(因此:它們原本就應該是同一個變數.)
一句話:這個規定是一種無可奈何.也說明:程式設計語言的設計是受到實現技術的限制的.這就是一例. 因為:我就看到不少人都持這種觀點:設計與想法是最重要的,實現的技術是無關緊要的,只要你作出設計與規定,都能實現.
Android(java)學習筆記150:為什麼局部內部類只能訪問外部類中的 final型的常量