ClassLoader.loadClass和Class.forName的區別

爲何要把ClassLoader.loadClass(String name)和Class.forName(String name)進行比較呢,由於他們都能在運行時對任意一個類,都可以知道該類的全部屬性和方法;對於任意一個對象,都可以調用它的任意方法和屬性。java

在比較它倆以前需先了解一下java類裝載的過程mysql

java類裝載過程分爲3步:sql

   

 

  1:加載數據庫

    Jvm把class文件字節碼加載到內存中,並將這些靜態數據裝換成運行時數據區中方法區的類型數據,在運行時數據區堆中生成一個表明這個類安全

  的java.lang.Class對象,做爲方法區類數據的訪問入口。jvm

  *釋:方法區不單單是存放方法,它存放的是類的類型信息。spa

  2:連接:執行下面的校驗、準備和解析步驟,其中解析步驟是可選的對象

    a:校驗:檢查加載的class文件的正確性和安全性blog

    b:準備:爲類變量分配存儲空間並設置類變量初始值,類變量隨類型信息存放在方法區中,生命週期很長,使用不當和容易形成內存泄漏。生命週期

    *:類變量就是static變量;初始值指的是類變量類型的默認值而不是實際要賦的值

    c:解析:jvm將常量池內的符號引用轉換爲直接引用

  3:初始化:執行類變量賦值和靜態代碼塊

 

在瞭解了類裝載過程以後咱們繼續比較兩者區別:

  • Classloder.loaderClass(String name)

    其實該方法內部調用的是:Classloder. loadClass(name, false)

    方法:Classloder. loadClass(String name, boolean resolve)

        1:參數name表明類的全限定類名

        2:參數resolve表明是否解析,resolve爲true是解析該類

  • Class.forName(String name)

    其實該方法內部調用的是:Class.forName(className, true, ClassLoader.getClassLoader(caller))

    方法:Class.forName0(String name, boolean initialize, ClassLoader loader)

      參數name表明全限定類名

      參數initialize表示是否初始化該類,爲true是初始化該類

      參數loader 對應的類加載器

  • 二者最大的區別

    Class.forName獲得的class是已經初始化完成的

    Classloder.loaderClass獲得的class是尚未連接的

  • 怎麼使用

    有些狀況是隻須要知道這個類的存在而不須要初始化的狀況使用Classloder.loaderClass,而有些時候又必須執行初始化就選擇Class.forName

    例如:數據庫驅動加載就是使用Class.froName(「com.mysql.jdbc.Driver」),

    下面咱們來看看Driver的源代碼:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

    public Driver() throws SQLException {

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

    從Driver的源碼中咱們能夠看出Driver這個類只有一個static塊,這樣咱們須要初始化後才能獲得DriverManager,因此咱們選擇使用Class.forName()

相關文章
相關標籤/搜索