1. 程式人生 > >匿名內部類和區域性內部類中只能訪問final變數的原因

匿名內部類和區域性內部類中只能訪問final變數的原因

在一個方法中,如果建立一個匿名內部類,並且在內部類中藥訪問方法的引數,我們必須將該引數用final進行修飾才能訪問,這個的原因主要是由於方法和內部類的生命週期不相同導致的。

當我們執行一個帶參的方法時,在該方法的呼叫棧中將生成一個區域性變數(即該引數),如果在該方法中建立了局部內部類,則jvm會產生一個inner_object,但是,此inner_object並不會隨著方法的執行完畢而銷燬。因此,當方法執行完畢之後,方法呼叫棧中的區域性變數也將銷燬,這個時候區域性內部類沒有被銷燬,就會發生之前能訪問的引數此時找不到了的尷尬情況。

而當我們使用final對引數進行修飾之後,jvm中將產生一個該引數的複製,區域性內部類不再直接訪問該引數,而是訪問這個引數的複製。這樣,當方法執行完畢,呼叫棧中的引數銷燬之後,區域性內部類依然可以訪問到這個引數在jvm中的複製,而不會發生異常。

上述的限制在Java8中已經不復存在了,從Java8開始,我們不再需要將引數定義為final,區域性內部類也可以正常的訪問方法中的引數。

In addition, a local class has access to local variables. However, a local class can only access local variables that are declared final. When a local class accesses a local variable or parameter of the enclosing block, it captures

 that variable or parameter. 

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final. 

Starting in Java SE 8, if you declare the local class in a method, it can access the method's parameters.



參考:

上述文章中詳細講解了內部類訪問方法引數這種看似天經地義的事情為什麼要多此一舉加個final修飾符的原因:這個規定是一種無可奈何.也說明:程式設計語言的設計是受到實現技術的限制的”