類的加載:Class.forName與ClassLoader.loadClass

 

Class.forNameClassLoader.loadClass方法都用來動態的加載一個類(都返回一個java.lang.Class對象),區別在於他們使用的ClassLoader和是否執行類的初始化。

1.1      Class.forName

這是一個類方法,該方法除了加載類到JVM中,還會執行類的初始化,即類的靜態初始化。

 

使用Class.forName最常用的形式是Class.forName(String qualifiedClassName),如寫JDBC程序常用到的加載某個數據庫Driverjvm的代碼:

Class.forName("com.mysql.jdbc.Driver");

該函數使用調用者的ClassLoader, 即調用該行代碼的類所使用的ClassLoader,返回一個參數名所對應的Class對象。

另外還有一個帶三個參數的forName方法, Class.forName(String, boolean, ClassLoader),參數分別用來指定類名,是否初始化和要使用的ClassLoader

1.2      ClassLoader.loadClass

這是一個實例方法,可以使用一個特定的ClassLoader來加載一個類。該方法不會執行類的初始化,只由當該類第一次被使用時纔會執行類的初始化,比如調用該類的一個靜態方法或創建該類的一個對象。

1.3      使用哪一個方法

1.3.1       ClassLoader

不同的ClassLoader加載類時會從不同的位置來查找類的.class文件,所以如果要加載的類不在默認的查找位置時,就應該指定要使用的ClassLoader,否則會得到java.lang.ClassNotFoundException的錯誤。爲了靈活性,你應該總是提供一個來參數指定ClassLoader而不是使用默認的ClassLoader,即使用帶三個參數的forNameloadClass方法。關於不同的ClassLoader如何查找及加載類請參考ClassLoder一文。

1.3.2       是否要執行類初始化

在上面加載Mysql Driver的例子中,我們本身並不需要創建MySqlDriver對象,只需要加載DriverJVM,並執行類的初始化(可能執行註冊自己到Driver Manger的代碼)。所以可以使用forName方法,如果使用ClassLoader.loadClass則需要像下面這樣:

ClassLoader cl = …;

cl.loadClass("com.mysql.jdbc.Driver").newInstance(); //創建對象僅僅爲了執行類初始化,對象本身並不會被使用。

 

如果已知類的初始化是一個比較耗時的過程,則可以將其初始化推遲到該類被一次使用時。另外執行類的初始化代碼失敗會拋出java.lang.ExceptionInInitializerError異常。此時加載的類就變得不可用。類的初始化錯誤往往很難跟蹤,所以如果要在一個特定點捕獲並處理該異常就可以使用Class.forName並放在一個try塊中。但是不要試圖重新加載該類,因爲一個類只能被同一個ClassLoader加載一次。

 

1.4      參考:

[ldcs] http://www.javaworld.com/javaworld/javaqa/2003-03/01-qa-0314-forname.html?page=1. 2003.03

 

 

發佈了40 篇原創文章 · 獲贊 2 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章