java兩種反射的區別 - Class.forName()和ClassLoader.loadClass()


在理解這兩種反射機制之前,需要弄清楚java類的加載機制.

裝載:通過類的全限定名獲取二進制字節流(二進制的class文件),將二進制字節流轉換成方法區中的運行時數據結構,在內存中生成Java.lang.class對象。這個時候該類型沒有被分配內存,設置默認值,也沒有初始化。

鏈接:執行下面的校驗、准備和解析步驟,其中解析步驟是可以選擇的;

  校驗:檢查導入類或接口的二進制數據的正確性;(文件格式驗證,元數據驗證,字節碼驗證,符號引用驗證)

  准備:給類的靜態變量分配並初始化存儲空間;

  解析:將常量池中的符號引用轉成直接引用;

初始化:激活類的靜態變量的初始化Java代碼和靜態Java代碼塊,並初始化程序員設置的變量值。

Class.forName有兩個重載方法:

 public static Class<?> forName(String name, boolean initialize,
                   ClassLoader loader)
        throws ClassNotFoundException


 public static Class<?> forName(String className) 
                throws ClassNotFoundException

解釋:

name:類的全限定名,如:com.org.prj
initialize:如果為true,則會在返回Class對象之前,對該類型做連接,校驗,初始化操作。(如:執行static塊中的代碼),initialize默認需要初始化。
loader:用自定義的類加載器來請求這個類型;當然,你也可以傳入null,用bootstrap加載器

由於Class.forName默認是需要初始化,一旦初始化,就會觸發目標對象的 static塊代碼執行,static參數也也會被再次初始化。

我們在來看ClassLoader.loadClass也有兩個兩個重載方法:

protected synchronized Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException

public Class<?> loadClass(String name) throws ClassNotFoundException 

解釋:

name:類的全限定名,如:com.org.prj

resolve:表示是否需要連接該類型。 僅僅是連接(這里面包括校驗class文件,准備分配內存,類型常量池的替換),並不會初始化該類型。

resolve默認是不鏈接,不進行鏈接意味着不進行包括初始化等一些列步驟,那么靜態塊和靜態對象就不會得到執行。

總結:

1.Class.forName返回的Class對象可以決定是否初始化。而ClassLoader.loadClass返回的類型絕對不會初始化,最多只會做連接操作。
2.Class.forName可以決定由哪個classLoader來請求這個類型。而ClassLoader.loadClass是用當前的classLoader去請求。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM