面試題分享
public class A {public static void fun1() {
System.out.println("fun1");
}
public void fun2() {
System.out.println("fun2");
}
public static void main(String[] args) {
((A) null).fun1();
((A) null).fun2();
}
}
題目:
以上程式碼是否可以編譯通過?
如可以通過,結果是什麼?答案:
程式碼可以編譯通過,null 可以強制轉為任意型別,呼叫其類中的靜態方法不報異常,呼叫其類中的非靜態方法會報空指標異常
理解
執行下面程式碼列印結果為 null:
A a = (A) null;
System.out.println(a);
由於將 null 強轉為 A 的物件,編譯上可以通過,
但是實際值仍然為 null,非靜態方法是屬於物件的方法,
所以呼叫非靜態方法會報空指標異常
執行以下程式碼不報異常:
A a2 = null;
a2.fun1();
由於 fun1 是靜態方法,靜態方法數隨著類載入而載入的,
所以 java 編譯器在編譯的過程中對我們的程式碼進行的了優化,
我們通過檢視 class 檔案即可看出,這兩行程式碼改變成為了下面的樣式:
A a2 = null;
fun1();
原因
java 編譯器對於 使用物件呼叫類中的靜態方法進行了優化。對於 a2.fun1() 給優化為 fun1()
java 推薦使用類名直接呼叫靜態方法 , 從而減少了編譯器的工作,提高了編譯效率。
如圖:左側為 java 原始檔,右側為編譯後的 class 檔案