天天看點

面試 - 反射中Class.forName()和ClassLoader.loadClass()的差別 ,判斷一個類是否已經被加載一 Java類裝載過程二 分析 Class.forName()和ClassLoader.loadClass

ClassLoader關鍵在于

加載  ->  連結(驗證+準備+解析) ->  初始化(使用前的準備) ->  使用  ->  解除安裝 

可以隻加載,不連結

ClassLoader.loadClass(className)

ClassLoader.loadClass(className,false)

也可以加載,并連結

Class.forName(className)

Class.forName(className,true,classloader);

判斷一個類是否已經被加載 (隻加載,不連結)

public static boolean isPresent(String name) {
    try {
        Thread.currentThread().getContextClassLoader().loadClass(name);
        return true;
    } catch (ClassNotFoundException e) {
        return false;
    }
}
           

一 Java類裝載過程

面試 - 反射中Class.forName()和ClassLoader.loadClass()的差別 ,判斷一個類是否已經被加載一 Java類裝載過程二 分析 Class.forName()和ClassLoader.loadClass

裝載:通過類的全限定名擷取二進制位元組流,将二進制位元組流轉換成方法區中的運作時資料結構,在記憶體(堆)中生成Java.lang.Class類對象; 

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

  校驗:檢查導入類或接口的二進制資料的正确性;(檔案格式驗證,中繼資料驗證,位元組碼驗證,符号引用驗證) 

  準備:給類的靜态變量配置設定并初始化存儲空間; (預設初始化)

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

初始化:激活類的靜态變量的初始化和靜态Java代碼塊的執行,并初始化程式員設定的變量值。

二 分析 Class.forName()和ClassLoader.loadClass

Class.forName(className)方法,内部實際調用的方法是  Class.forName(className,true,classloader);

第2個boolean參數表示類是否需要初始化,  Class.forName(className)預設是需要初始化。

一旦初始化,就會觸發目标對象的 static塊代碼執行,static參數也也會被再次初始化。

ClassLoader.loadClass(className)方法,内部實際調用的方法是  ClassLoader.loadClass(className,false);

第2個 boolean參數,表示目标對象是否進行連結,false表示不進行連結,由上面介紹可以,

不進行連結意味着不進行包括初始化等一些列步驟,那麼靜态塊和靜态對象就不會得到執行。

consult :

https://blog.csdn.net/x_iya/rticle/details/73199280

https://www.cnblogs.com/yunger/p/5760444.html

繼續閱讀