class.forName與classLoader區別

題記:

記錄一下java反射中的一些面試問題html

區別:

@CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

第二個參數是true,表示是否初始化,默認是初始化,一旦初始化,就會出發對象的靜態代碼塊和靜態參數的初始化,請看類的裝在過程java

加載:經過累的全限定名獲取二進制字節流,將二進制字節流轉換成方法區中的運行時數據結構,在內存中生成Java.lang.class對象; 

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

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

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

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

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

 代碼示例:

@Data
@Builder
public class Product implements Serializable {

    private static String staticMethod = staticMethod();

    static {
        System.out.println("靜態代碼塊執行");
    }

    private String name;

    private String address;

    private static String staticMethod(){

        System.out.println("靜態方法執行");
        return "靜態方法塊執行";
    }

}

執行實例:

public class Demo2 {

    @Test
    public void test1() throws ClassNotFoundException {
        System.out.println("class.forName 執行================");
        Class.forName("com.edward.sg.owner.server.Product");
        System.out.println("classLoader 執行=================");
        ClassLoader.getSystemClassLoader().loadClass("com.edward.sg.owner.server.Product");
    }

}

執行結果 

class.forName 執行================
靜態方法執行
靜態代碼塊執行
classLoader 執行=================

classLoader執行結果能夠看出沒有進行類的初始化,只是將類加載到虛擬機中,class.forName進行類的初始化程序員

jdbc中使用了class.forname進行類的初始化,加載靜態方法面試

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

DriverManager.registerDriver(new Driver())和 Class.forName(),其中DriverManager.registerDriver會致使實例化了兩次Driver與Driver初始化的時候運行靜態代碼塊相關sql

Spring IoC 的 Lazy loading 有關, Spring IoC 爲了加快初始化速度, 所以大量使用了延時加載技術. 而使用 classloader 不須要執行類中的初始化代碼, 能夠加快加載速度, 把類的初始化工做留到實際使用到這個類的時候(感興趣的同窗還能夠看看 IOC中的循環依賴的問題 https://www.jianshu.com/p/f0c005c7354b數據結構

歡迎關注做者公衆號交流以及投稿ui

ref:code

http://www.javashuo.com/article/p-pwygcsas-be.htmlserver

https://www.cnblogs.com/zabulon/p/5826610.htmlhtm

相關文章
相關標籤/搜索