簡體   English   中英

如何將變量標記為最終允許內部類訪問它們?

[英]How does marking a variable as final allow inner classes to access them?

在方法內部定義的內部類不能訪問方法的局部變量,除非這些局部變量標記為final我已經查看了堆棧溢出和java代碼牧場中的其他帖子,但它們似乎都沒有完全回答關於如何標記變量final允許內部類訪問方法中的局部變量。

class MyOuter {
    private String x = "Outer";

    void fly(final int speed) {
        final int e = 1;
        class FlyingEquation {

            public void seeOuter()
            {
                System.out.println("Outer x is " + x);
            }
            public void display()
            {
                System.out.println(e);// line 1
                System.out.println(speed);// line 2
            }
        }
        FlyingEquation f=new FlyingEquation();
        f.seeOuter();
        f.display();
    }       
    public static void main(String args[])
    {
        MyOuter mo=new MyOuter();
        mo.fly(5);
    }
}

我發現的解釋:

局部變量存儲在堆棧中,一旦方法調用完成,就會彈出堆棧並且本地變量不可訪問,而最終局部變量存儲在內存的數據部分中,可能允許JVM在方法調用結束后訪問它們。 data section of memorydata section of memory在哪里? 我相信所有局部變量fi​​nal或not都存儲在堆棧中。當從堆棧中刪除方法時,最終變量將被刪除。 最終變量中的值是否與堆中的對象一起存儲?

它不支持非final字段,因為它們可以通過方法或類進行更改,但這不受支持,因為實際上有兩個不同的字段/變量。

將局部變量標記為final表示編譯器保證其值在分配后不會更改。 這使得編譯器可以安全地在內部類中創建合成字段,並在構造內部類實例時將局部變量的值復制到此合成字段中。 從內部類代碼中讀取局部變量實際上編譯為合成字段的讀取。

這個技巧對於非最終變量不起作用,因為它們可能在實例化內部類之后發生變化,並且合成字段將與原始變量不同步。

重要的是要意識到所有內部類都是編譯器的技巧 - 對於運行時JVM,所有類(頂級,嵌套靜態和內部)都被視為相同。

在內部類的實例化期間,當方法和類都在范圍內時,內部類將復制作為常量的變量,這意味着該方法可能超出范圍,因為內部類僅使用變量的副本。 看看這篇文章

是的,最終的局部變量保存在堆棧中,並在方法從堆棧中刪除時被銷毀。 正如@Ian所建議的,當編譯器看到變量的final關鍵字時,它會在堆上的內部類對象中創建值的副本。

這背后的故事是java的創建者沒有足夠的時間來完全支持關閉

有幾種方法可以使語言支持關閉。 例如,在方案中,函數中的自由參數被綁定到與定義函數的詞法范圍相對應的環境。 在強制不可變數據(如SML)的語言中,可以通過將閉包所需的局部變量復制到堆來實現閉包。

因此,他們創造了內部階級,以便有一個窮人的封閉版本,模仿ML的風格。

方法本地內部類不能使用外部方法的局部變量,直到該局部變量未聲明為final。 我們需要將局部變量聲明為final的主要原因是局部變量存在於堆棧中,直到方法在堆棧上,但可能存在內部類的對象仍然存在於堆上的情況。

結帳這篇文章: http//www.geeksforgeeks.org/inner-class-java/

所以現在考慮一下。該方法的局部變量存在於堆棧中 ,僅存在於方法的生命周期中。 我們已經知道局部變量的范圍僅限於聲明變量的方法。當方法結束時,堆棧幀被吹走,變量是歷史。 但即使在方法完成之后,在其中創建的內部類對象仍可能在堆上存活,例如,如果對它的引用被傳遞到其他代碼中,然后存儲在實例變量中。 因為局部變量不保證只要方法本地內部類對象存在,所以內部類對象不能使用它們。 除非局部變量標記為final

最終的局部變量是否存儲在堆而不是堆棧中?

說明:現在經過SO的一些研究后發現,當方法執行結束時,所有局部變量( final或not )都存儲到堆棧中並超出范圍。

但是關於最終變量JVM將這些作為常量,因為它們在啟動后不會改變。 當一個內部類試圖訪問這些編譯器創建變量(不是可變它自己)到堆中的副本,並創建內部類中的合成場 ,所以即使在方法執行結束這是因為內訪問class有它自己的副本。 提交的合成字段實際上不存在於源代碼中,但編譯器在某些內部類中創建這些字段以使這些字段可訪問。 在簡單的單詞隱藏領域。

所以最終變量也存儲在堆棧中,但是內部類存儲在堆中的變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM