[英]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 memory
的data section of memory
在哪里? 我相信所有局部變量final或not都存儲在堆棧中。當從堆棧中刪除方法時,最終變量將被刪除。 最終變量中的值是否與堆中的對象一起存儲?
它不支持非final字段,因為它們可以通過方法或類進行更改,但這不受支持,因為實際上有兩個不同的字段/變量。
將局部變量標記為final
表示編譯器保證其值在分配后不會更改。 這使得編譯器可以安全地在內部類中創建合成字段,並在構造內部類實例時將局部變量的值復制到此合成字段中。 從內部類代碼中讀取局部變量實際上編譯為合成字段的讀取。
這個技巧對於非最終變量不起作用,因為它們可能在實例化內部類之后發生變化,並且合成字段將與原始變量不同步。
重要的是要意識到所有內部類都是編譯器的技巧 - 對於運行時JVM,所有類(頂級,嵌套靜態和內部)都被視為相同。
在內部類的實例化期間,當方法和類都在范圍內時,內部類將復制作為常量的變量,這意味着該方法可能超出范圍,因為內部類僅使用變量的副本。 看看這篇文章 。
是的,最終的局部變量保存在堆棧中,並在方法從堆棧中刪除時被銷毀。 正如@Ian所建議的,當編譯器看到變量的final關鍵字時,它會在堆上的內部類對象中創建值的副本。
這背后的故事是java的創建者沒有足夠的時間來完全支持關閉 。
有幾種方法可以使語言支持關閉。 例如,在方案中,函數中的自由參數被綁定到與定義函數的詞法范圍相對應的環境。 在強制不可變數據(如SML)的語言中,可以通過將閉包所需的局部變量復制到堆來實現閉包。
因此,他們創造了內部階級,以便有一個窮人的封閉版本,模仿ML的風格。
方法本地內部類不能使用外部方法的局部變量,直到該局部變量未聲明為final。 我們需要將局部變量聲明為final的主要原因是局部變量存在於堆棧中,直到方法在堆棧上,但可能存在內部類的對象仍然存在於堆上的情況。
所以現在考慮一下。該方法的局部變量存在於堆棧中 ,僅存在於方法的生命周期中。 我們已經知道局部變量的范圍僅限於聲明變量的方法。當方法結束時,堆棧幀被吹走,變量是歷史。 但即使在方法完成之后,在其中創建的內部類對象仍可能在堆上存活,例如,如果對它的引用被傳遞到其他代碼中,然后存儲在實例變量中。 因為局部變量不保證只要方法本地內部類對象存在,所以內部類對象不能使用它們。 除非局部變量標記為final 。
最終的局部變量是否存儲在堆而不是堆棧中?
說明:現在經過SO的一些研究后發現,當方法執行結束時,所有局部變量( final或not )都存儲到堆棧中並超出范圍。
但是關於最終變量JVM
將這些作為常量,因為它們在啟動后不會改變。 當一個內部類試圖訪問這些編譯器創建變量(不是可變它自己)到堆中的副本,並創建內部類中的合成場 ,所以即使在方法執行結束這是因為內訪問class有它自己的副本。 提交的合成字段實際上不存在於源代碼中,但編譯器在某些內部類中創建這些字段以使這些字段可訪問。 在簡單的單詞隱藏領域。
所以最終變量也存儲在堆棧中,但是內部類存儲在堆中的變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.