1. 程式人生 > >反射中,Class.forName 和 classloader 的區別

反射中,Class.forName 和 classloader 的區別

https://blog.csdn.net/qq_27093465/article/details/52262340

java中class.forName()和classLoader都可用來對類進行載入。

類載入過程為: 載入-->連結-->初始化;

載入:通過累的全限定名獲取二進位制位元組流,將二進位制位元組流轉換成方法區中的執行時資料結構,在記憶體中生成Java.lang.class物件;

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

  校驗:檢查匯入類或介面的二進位制資料的正確性;(檔案格式驗證,元資料驗證,位元組碼驗證,符號引用驗證)

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

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

初始化:啟用類的靜態變數的初始化Java程式碼和靜態Java程式碼塊,並初始化程式設計師設定的變數值。

1、Class.forName(className)方法,原始碼如下:

//Class.forName(String className)  這是1.8的原始碼
public static Class<?> forName(String className) throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        
return forName0(className, true, ClassLoader.getClassLoader(caller), caller); } //注意第二個引數,是指Class被loading後是不是必須被初始化。 不初始化就是不執行static的程式碼即靜態程式碼

第二個引數代表是否需要初始化,預設為true代表進行初始化一旦初始化,就會觸發目標物件的 static塊程式碼執行,static引數也也會被再次初始化。2、ClassLoader.loadClass(className)方法

   內部實際呼叫的方法是 ClassLoader.loadClass(className, false);

  第2個 boolean引數,表示目標物件是否進行連結,false表示不進行連結,由上面介紹可以,不進行連結意味著不進行包括初始化等一些列步驟,那麼靜態塊和靜態物件就不會得到執行。

 

結論

class.forName()前者除了將類的.class檔案載入到jvm中之外,還會對類進行解釋,執行類中的static塊。

classLoader只幹一件事情,就是將.class檔案載入到jvm中,不會執行static中的內容,只有在newInstance才會去執行static塊。

 

問題:資料庫連結為什麼使用Class.forName(className)

JDBC  Driver原始碼如下, 因為使用Class.forName(classname) 才能在反射回去類的時候執行static塊。

 

static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
    }
}