面試會問的-java反射(包括簡述類加載流程)

1、jvm 如何構建一個實例?

創建對象過程:

A a = new A() ;

  1. 加載類{ClassLoader 加載 .class 文件到內存1. 經過javac 編譯後的 字節碼(.class)文件 被 ClassLoader 加載進內存 (進入方法區);
    2. 在方法區中 生成 Class 對象 - Class 對象;
    3. 創建實例對象;
    4. 將實例對象放入 堆中 ;
    ​執行靜態代碼塊 和 靜態初始化語句}
  2. 執行 new ,申請一片內存空間;
  3. 調用構造器,創建一個空白對象;
  4. 子類調用父類構造器;
  5. 構造器執行{執行構造代碼塊和初始化語句構造器內容}

通過 new 創建實例對象和反射創建實例,都繞不開 Class 對象。

2、類加載器 加載 .class 文件:

分為三步驟:

1. 檢查1是否已經加載,有就直接返回,避免重複加載;
  1. 當前緩存中確實沒有該類,遵循父優先加載機制,加載 .class文件;
  2. 上面兩步都失敗,調用 findClass() 方法加載。

注: ClassLoader 類本身是抽象類,不能通過 new 創建對象。因此 ClassLoader 中的 findClass() 方法 只用來拋出異常。就是說 父類 ClassLoader 中的 findClass() 無法加載 .class 文件。

ClassLoader 類中的 findClass() 方法 :

protected Class  findClass(String var1) throws ClassNotFoundException {
 throw new ClassNotFoundException(var1);
}

根據需求重寫父類 findClass() 方法。

defineClass() ClassLoader 定義的方法,目的是 根據 .class 文件的字節數組 byte[] b 造出對應的 Class 對象 ( Class )。

面試會問的-java反射(包括簡述類加載流程)

類加載流程

2、反射 API 日常開發的主要作用:

  • 創建對象
  • 反射調用方法

創建實例的難點在於,很多人不知道clazz.newInstance()底層還是調用Contructor對象的newInstance()。所以,要想調用clazz.newInstance(),必須保證編寫類的時候有個無參構造。


分享到:


相關文章: