Class.forName和ClassLoader有啥區別?

ava中的Class.forName()和ClassLoader 均可以對類進行加載,在學習mysql期間可能會常常用到Class.forName(),ClassLoader負責將Class的字節碼形式轉換成內存形式的 Class 對象。字節碼能夠來自於磁盤文件,也就是XXXX.class,也能夠來自jar包裏的XXXX.class,也能夠來自遠程服務器提供的字節流,字節碼的本質就是一個字節數組[]byte。java

實際上Class.forName()方法也是調用的 ClassLoader 來實現的。forName方法最後調用 forName0(本地方法),第二個參數被默認設置爲了 true,這個參數表明是否對加載的類進行初始化,設置爲 true 時會類進行初始化,表明會執行類中的靜態代碼塊,以及對靜態變量的賦值等操做。mysql

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

他還有個重載方法,能夠手動選擇在加載類時是否要對其類進行初始化。sql

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

編寫一個類測試一下。數據庫

public class Test {
    static {
        System.out.println("靜態代碼快");
    }
    public static final String title=getTitle();

    private static String getTitle(){
        System.out.println("執行getTitle()");
        return "TITLE";
    }
}

測試方法:數組

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.hxl.Test");
    }
}

運行結果:服務器

靜態代碼快
執行getTitle()

根據運行結果得出 Class.forName 加載類時將類進了初始化,再看Classloader。ide

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
      ClassLoader.getSystemClassLoader().loadClass("com.hxl.Test");
    }
}

而 ClassLoader 的 loadClass 並無對類進行初始化,只是把類加載到了虛擬機中。學習

最後在說說JDBC,咱們使用 JDBC 時一般是使用 Class.forName() 方法來加載數據庫鏈接驅動。這是由於在 JDBC 規範中明確要求 Driver(數據庫驅動)類必須向 DriverManager 註冊本身。測試

以 MySQL 的驅動爲例,咱們看到 Driver 註冊到 DriverManager 中的操做寫在了靜態代碼塊中,這就是爲何在寫 JDBC 時使用 Class.forName() 的緣由了。ui

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()    }}
相關文章
相關標籤/搜索