2020年Java基礎面試題及答案彙總

 什麼情況下會觸發類的初始化?

  (1)、遇到 new, getstatic, putstatic, invokestatic 這4條字節碼指令。

  (2)、使用 java.lang.reflect 包的方法對類進行反射調用。

  (3)、初始化一個類的時候,如果發現其父類還沒有進行過初始化,則先初始化其父類(注意:

  如果是接口的話,則不要求初始化父類)。

  (4)、當虛擬機啟動時,用戶需要指定一個要執行的主類(包含 main()方法的那個類),虛擬機會先初始化這個主類。

  (5)、當使用JDK 1.7 的動態語言支持時,如果一個 java.lang.invoke.MethodHandle 實例最後的解析結果 REF_getstatic, REF_putstatic, REF_invokeStatic的方法句柄,並且這個方法句柄所對應的類沒有進行過初始化,則先觸發其初始化。

  外加幾種不會初始化的例子:

  (1)、同類子類引用父類的靜態字段,不會導致子類初始化。至於是否會觸發子類的加載和驗證,則取決於虛擬機的具體實現。

  (2)、通過數組定義來引用類,也不會觸發類的初始化。例如下面這個語句:

  1Animal[] a = new Animao[10];

  並不會觸發 Animal 類的初始化。

  (3)、引用一個類的常量也不會觸發初始化。

  談談你對解析與分派的認識。

  1.方法在程序真正運行之前就有一個可確定的調用版本,並且這個方法的調用版本在運行期間是不可變的,即“編譯時可知,運行不可以變”,這類目標的方法的調用稱之為解析。

  Java 語言中符合“編譯器可知,運行期不可變”這個要求的方法,主要包括靜態方法和私有方法兩大類。

  2.解析調用一定是個靜態的過程,在編譯期就完全確定,在類加載的解析階段就將涉及的符號引用全部轉變為可以確定的直接引用,不會延遲到運行期再去完成。而分派(Dispatch)調用則可能是靜態的也可能是動態的。於是分派方式就有靜態分派和動態分派。

  下面我來解釋下靜態分派和動態分派。

  靜態分派

  看下面這段程序

  1//定義幾個類 2 3public abstract class Animal { 4 } 5class Dog extends Animal{ 6 } 7class Lion extends Animal{ 8 } 910class Test4{ 11 public void run(Animal animal){12 System.out.println("動物跑啊跑");13 }14 public void run(Dog dog){15 System.out.println("小狗跑啊跑");16 }17 public void run(Lion lion){18 System.out.println("獅子跑啊跑");19 } 20 //測試21 public static void main(String[] args){22 Animal dog = new Dog();23 Animal lion = new Lion();;24 Test4 test4 = ew Test4();25 test4.run(dog);26 test4.run(lion);27 }28}

  運行結果是

  動物跑啊跑

  動物跑啊跑

  相信大家學過重載的都能猜到是這個結果。但是,為什麼會選擇這個方法進行重載呢?虛擬機是如何選擇的呢?

  在此之前我們先來了解兩個概念。

  先來看一行代碼:

  Animal dog = new Dog();

  對於這一行代碼,我們把Animal稱之為變量dog的靜態類型,而後面的Dog稱為變量dog的實際類型。

  現在我們再來看看虛擬機是根據什麼來重載選擇哪個方法的。

  對於靜態類型相同,但實際類型不同的變量,虛擬機在重載的時候是根據參數的靜態類型而不是實際類型作為判斷選擇的。並且靜態類型在編譯器就是已知的了,這也代表在編譯階段,就已經決定好了選擇哪一個重載方法。

  由於dog和lion的靜態類型都是Animal,所以選擇了run(Animal animal)這個方法。

  靜態分派的典型應用就是方法的重載的,現在應該知道什麼是靜態分派了吧?

  動態分派

  和靜態分派類似,所謂動態分派就是就是根據方法的實際類型來選擇調用哪個方法,而實際類型是需要到達運行期才能知道。像重寫就是動態分派的典型應用了。

  如何定義個類加載器?你使過哪些或者你在什麼場景下需要個定義的類加載器嗎?

  可以把自己自定義的類加載器繼承 ClassLoader,然後重寫 findClass() 方法,把自己的類加載邏輯寫到 findClass() 方法中去。

  使用類加載器的場景:

  加載特定路徑的 class 文件

  熱部署加載 class 文件

  從網絡中加載一個加密的 class 文件


原文:2020年Java基礎面試題及答案彙總


分享到:


相關文章: