Class.forName得到的class是已經初始化完成的,Classloder.loaderClass得到的class是還沒有鏈接的這是二者之間最大的區別 ...
為什麼要把ClassLoader.loadClass(String name)和Class.forName(String name)進行比較呢,因為他們都能在運行時對任意一個類,都能夠知道該類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性。
在比較它倆之前需先瞭解一下java類裝載的過程
java類裝載過程分為3步:
1:載入
Jvm把class文件位元組碼載入到記憶體中,並將這些靜態數據裝換成運行時數據區中方法區的類型數據,在運行時數據區堆中生成一個代表這個類
的java.lang.Class對象,作為方法區類數據的訪問入口。
*釋:方法區不僅僅是存放方法,它存放的是類的類型信息。
2:鏈接:執行下麵的校驗、準備和解析步驟,其中解析步驟是可選的
a:校驗:檢查載入的class文件的正確性和安全性
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()