Java編寫代碼過程中遇到了一個問題,main方法中創建內部類的實例時,編譯階段出現錯誤,查看錯誤描述:
No enclosing instance of type Test is accessible. Must qualify the allocation with an enclosing instance of type Test (e.g. x.new A() where x is an instance of Test).
經過查證,是因為內部類是動態的(無static關鍵字修飾),而main方法是靜態的,普通的內部類對象隱含地保存了一個引用,指向創建它的外圍類對象,所以要在static方法(類加載時已經初始化)調用內部類的必須先創建外部類。即應該這樣創建“DanymicTest test = new StaticCallDynamic().new DanymicTest();”其中StaticCallDynamic為外部類,DanymicTest為內部動態類;如果將內部內修改為靜態類,可以在main中直接創建內部類實例。
順便看了下靜態方法對動態方法的調用,如果在靜態方法中直接調用靜態方法,其中print()為類中的動態方法,會出現如下問題:
Cannot make a static reference to the non-static method print() from the type StaticCallDynamic
這個要從java的內存機制去分析,首先當你New 一個對象的時候,並不是先在堆中為對象開辟內存空間,而是先將類中的靜態方法(帶有static修飾的靜態函數)的代碼加載到一個叫做方法區的地方,然后再在堆內存中創建對象。所以說靜態方法會隨着類的加載而被加載。當你new一個對象時,該對象存在於對內存中,this關鍵字一般指該對象,但是如果沒有new對象,而是通過類名調用該類的靜態方法也可以。
程序最終都是在內存中執行,變量只有在內存中占有一席之地時才會被訪問,類的靜態成員(變態和方法)屬於類本身,在類加載的時候就會分配內存,可以通過類名直接去訪問,非靜態成員(變量和方法)屬於類的對象,所以只有在類的對象產生(創建實例)的時候才會分配內存,然后通過類的對象去訪問。在一個類的靜態成員中去訪問非靜態成員之所以會出錯是因為在類的非靜態成員不存在的時候靜態成員就已經存在了,訪問一個內存中不存在的東西當然會出錯。
就類中的靜態方法不能調用動態方法,所以要么將動態方法也改為靜態方法(static),要么通過創建該靜態方法所在的實例(new 靜態c)再通過實例(c.d動態)來調用。