1. 程式人生 > >java靜態方法不能呼叫非靜態方法的原因

java靜態方法不能呼叫非靜態方法的原因

靜態方法是屬於類的,即靜態方法是隨著類的載入而載入的,在載入類時,程式就會為靜態方法分配記憶體,而非靜態方法是屬於物件的,物件是在類載入之後建立的,也就是說靜態方法先於物件存在,當你建立一個物件時,程式為其在堆中分配記憶體,一般是通過this指標來指向該物件。靜態方法不依賴於物件的呼叫,它是通過‘類名.靜態方法名’這樣的方式來呼叫的。而對於非靜態方法,在物件建立的時候程式才會為其分配記憶體,然後通過類的物件去訪問非靜態方法。因此在物件未存在時非靜態方法也不存在,靜態方法自然不能呼叫一個不存在的方法。

延伸一個相似的例子吧,在做一個筆試的時候遇到的問題:

有下面這樣的程式:

public class Test{

private static void Print(){
System.out.println("Print()");
}

public static void main(String[] args) {

((Test)null).Print();

}

}

問輸出什麼?

//輸出是Print()

當時看到這道題的時候真的是萬臉懵逼,為什麼類名那裡還要加一個null,為什麼不是直接Test.Print(),還以為這樣寫會報錯,然而並不是。經過查資料和某人的幫助,終於明白啦。

(1)首先,我們可以試一下去掉static,這裡不會編譯錯誤,但是執行時會丟擲空指標異常,原因是什麼呢,原因就是類似於上面說的靜態方法不能呼叫非靜態方法的原因了。我們很容易被null轉移了視線,這裡與null的關係不大(這是因為是靜態方法,null沒有影響),null是為了告訴我們這裡的引用沒有指向任何地方或者說還未初始化,也就是說物件未建立,從上面物件的建立過程可以知道,如果物件還未建立,則不會有this指標的引用,因此會報空指標異常。

(2)這裡用null的話(即(Test)null)是將Test引用強制轉換為Test物件,這樣也可以呼叫靜態方法,其實不需要null,也是可以呼叫靜態方法的,即Test.Print()。

另外補充一下我覺得很有必要知道的null的知識:

(1)null可以被強制轉換為任何引用型別。

(2)任何含有null值的包裝類在自動拆箱成基本資料型別時都會丟擲一個空指標異常

(3)不能用一個值為null的引用型別變數來呼叫非靜態方法,這樣會丟擲空指標異常,但是靜態方法可以被一個值為null的引用型別變數呼叫而不會丟擲空指標異常。這和物件的建立和靜態方法以及非靜態方法之間的關係有關。也就是上面說的那些。