爲何要把ClassLoader.loadClass(String name)和Class.forName(String name)進行比較呢,由於他們都能在運行時對任意一個類,都可以知道該類的全部屬性和方法;對於任意一個對象,都可以調用它的任意方法和屬性。java
在比較它倆以前需先了解一下java類裝載的過程mysql
java類裝載過程分爲3步:sql
1:加載數據庫
Jvm把class文件字節碼加載到內存中,並將這些靜態數據裝換成運行時數據區中方法區的類型數據,在運行時數據區堆中生成一個表明這個類安全
的java.lang.Class對象,做爲方法區類數據的訪問入口。jvm
*釋:方法區不單單是存放方法,它存放的是類的類型信息。ide
2:連接:執行下面的校驗、準備和解析步驟,其中解析步驟是可選的url
a:校驗:檢查加載的class文件的正確性和安全性對象
b:準備:爲類變量分配存儲空間並設置類變量初始值,類變量隨類型信息存放在方法區中,生命週期很長,使用不當和容易形成內存泄漏。blog
*釋:類變量就是static變量;初始值指的是類變量類型的默認值而不是實際要賦的值
c:解析:jvm將常量池內的符號引用轉換爲直接引用
3:初始化:執行類變量賦值和靜態代碼塊
在瞭解了類裝載過程以後咱們繼續比較兩者區別:
其實該方法內部調用的是:Classloder. loadClass(name, false)
方法:Classloder. loadClass(String name, boolean resolve)
1:參數name表明類的全限定類名
2:參數resolve表明是否解析,resolve爲true是解析該類
其實該方法內部調用的是:Class.forName(className, true, ClassLoader.getClassLoader(caller))
方法:Class.forName0(String name, boolean initialize, ClassLoader loader)
參數name表明全限定類名
參數initialize表示是否初始化該類,爲true是初始化該類
參數loader 對應的類加載器
兩種方式的區別
forName("")獲得的class是已經初始化完成的
loadClass("")獲得的class是尚未鏈接的
通常狀況下,這兩個方法效果同樣,都能裝載Class。
但若是程序依賴於Class是否被初始化,就必須用Class.forName(name)了。
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表示不進行連接,由上面介紹能夠, 不進行連接意味着不進行包括初始化等一些列步驟,那麼靜態塊和靜態對象就不會獲得執行
3.舉例說明他們各自的使用方法
java使用JDBC鏈接數據庫時候,咱們首先須要加載數據庫驅動。
Class.forName("com.MySQL.jdbc.Driver");//經過這種方式將驅動註冊到驅動管理器上
Connection conn = DriverManager.getConnection("url","userName","password");//經過驅動管理器得到相應的鏈接
查看com.mysql.jdbc.Driver源碼:
public class Driver extends NonRegisteringDriver
implements java.sql.Driver
{
//注意,這裏有一個static的代碼塊,這個代碼塊將會在class初始化的時候執行
static
{
try
{
//將這個驅動Driver註冊到驅動管理器上
DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
}
Class.forName("com.mysql.jdbc.Driver")方法之後,他會進行class的初始化,執行static代碼塊。 也就是說class初始化之後,就會將驅註冊到DriverManageer上,以後才能經過DriverManager去獲取相應的鏈接。 可是要是咱們使用ClassLoader.loadClass(com.mysql.jdbc.Driver)的話,不會link,更也不會初始化class。 相應的就不會回將Driver註冊到DriverManager上面,因此確定不能經過DriverManager獲取相應的鏈接。