內部類訪問局部變量的時候,爲什麼變量必須加上final修飾(轉)

這裏的局部變量就是在類方法中的變量,能訪問方法中變量的類當然也是局部內部類了。 我們都知道,局部變量在所處的函數執行完之後就釋放了,但是內部類對象如果還有引用指向的話它是還存在的。例如下面的代碼:

class Outer{                                                                       
        public static void main(String[] args){
                Outer out = new Outer();
                Object obj = out.method();
        }   

        Object method(){
                int locvar = 1;
                class Inner{
                        void displayLocvar(){
                                System.out.println("locvar = " + locvar);
                        }
                }
                Object in = new Inner();
                return in; 
        }
}

當out.method()方法執行結束後,局部變量 locvar 就消失了,但是在method()方法中 obj in = new Inner() 產生的 in 對象還存在引用obj,這樣對象就訪問了一個不存在的變量,是不允許的。這種矛盾是由局部內部類可以訪問局部變量但是局部內部類對象和局部變量的生命週期不同而引起的。

局部內部類訪問局部變量的機制

在java中,類是封裝的,內部類也不例外。我們知道,非靜態內部類能夠訪問外部類成員是因爲它持有外部類對象的引用 Outer.this, 就像子類對像能夠訪問父類成員是持有父類對象引用super一樣。局部內部類也和一般內部類一樣,只持有了Outer.this,能夠訪問外部類成員,但是它又是如何訪問到局部變量的呢?

實際上java是將局部變量作爲參數傳給了局部內部類的構造函數,而將其作爲內部類的成員屬性封裝在了類中。我們看到的內部類訪問局部變量實際上只是訪問了自己的成員屬性而已,這和類的封裝性是一致的。那麼上面的代碼實際上是這樣:

Object method(){
                int locvar = 1;
                class Inner{
                    private int obj;
                    public Inner(int obj){
                        this.obj = obj;
                    }
                        void displayLocvar(){
                                System.out.println("locvar = " + locvar);
                        }
                }
                Object in = new Inner(locvar);  //將locvar作爲參數傳給構造,以初始話成員
                return in; 
        }

那麼問題又來了,我們寫代碼的目的是在內部類中直接控制局部變量和引用,但是java這麼整我們就不高興了,我在內部類中整半天想着是在操作外部變量,結果你給整個副本給我,我搞半天丫是整我自己的東西啊?要是java不這麼整吧,由破壞了封裝性--------你個局部內部類牛啊,啥都沒有還能看局部變量呢。這不是java風格,肯定不能這麼幹。這咋整呢? 想想,類的封裝性咱們一定是要遵守的,不能破壞大局啊。但又要保證兩個東西是一模一樣的,包括對象和普通變量,那就使用final嘛,當傳遞普通變量的之前我把它變成一個常量給你,當傳遞引用對象的時候加上final就聲明瞭這個引用就只能指着這一個對象了。這樣就保證了內外統一。

轉自:https://segmentfault.com/a/1190000002735907

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章