2012-08-10 72 views
1

爲什麼方法 - 本地內部類不能使用封閉方法內聲明的變量,除了那些標記爲final的變量,我知道在封閉方法內聲明的變量可能會消失內部類實例仍然有效,但是當這個變量/ s被聲明爲最終時發生了什麼變化?方法 - 本地內部類不能使用在方法中聲明的變量

+0

[爲什麼只有最終變量可以在匿名類中訪問?](http://stackoverflow.com/questions/4732544/why-are-only-final-variables-accessible-in-anonymous-class) – assylias 2012-08-10 14:45:04

+0

重複http://stackoverflow.com/questions/10338708/inner-class-and-local-variables/20625906#20625906 – user1923551 2013-12-17 06:51:53

+0

我已經添加了答案。希望它可以幫助你 – 2016-03-02 05:54:02

回答

2

的原因是,它是在Java Language Specification #8.1.3

指定的任何局部變量,形式參數,或使用了何種異常參數,但在一個內部類沒有聲明必須聲明爲final。

還要注意的是Lambda項目(Java 8),其目的是在Java中引入閉包(更換匿名類),引入有效地最終的概念,這將讓你lambda表達式中使用非最終變量只要你不在封閉內修改它。

0

最終確保您不會失去對該變量的引用。你不希望你的內部類破壞或失去你的引用,因爲你可能會繼續在聲明的上下文中使用它。

1

原因是[實際從Where are Java final local variables stored?結論:final variables are copied by the compiler into a hidden member variable of the inner class that references it. This way, they are guaranteed to not change after the copy has been made.

而且可能是:該方法-局部內部類,這是在堆上並且其在棧上具有不同的範圍可變。但是,如果局部變量由final標記,它將存儲在堆中。

1

當變量是最終的時候,副本放在內部類中。即它仍然不能訪問變量,但它有一個它可以使用的副本。

如果您使用反射或調試器,您可以看到這些副本。

1

現在開始我想在點亮

是否最終局部變量獲得存儲在堆中,而不是堆 ?

說明:現在在後,所以我發現,所有的局部變量(最終還是沒有)存儲到和走出去的範圍 當方法執行結束一些研發。

但是關於最後的 變量JVM把這些作爲一個常數,因爲 啓動後它們不會改變。並且當內部類試圖訪問這些編譯器創建 該變量的副本(未變量它自我)插入 並創建內部類內部的合成字段,所以即使當 的方法執行是因爲內部類 有它自己的副本。 提交的合成域實際上不存在源代碼中的 ,但編譯器在某些內部類中創建這些域以使這些域可訪問。在簡單的文字中隱藏 字段。

因此,最終變量也存儲在堆棧中,但複製了內部類存儲在堆中的變量。

所以現在想想方法的後援局部變量存在於棧中,只限於對方法的生命週期存在。我們已經知道局部變量的範圍僅限於聲明變量的方法。當方法結束時,堆棧幀被吹走並且變量是歷史記錄。但即使在方法完成之後,如果其中創建的內部類對象可能仍然存在於堆中,例如,對它的引用被傳遞到其他代碼中,然後存儲在實例變量中。因爲只要局部內部類的對象是局部變量就不能保證活動,內部類對象不能使用它們。除非局部變量標記爲最終。而且它可以像合成領域一樣保持變化的最終效果。

+0

沒有人讀過我的答案:(?? – 2016-03-02 05:33:59