虛擬機(jī)加載類的途徑
1、由 new 關(guān)鍵字創(chuàng)建一個(gè)類的實(shí)例
在由運(yùn)行時(shí)刻用 new 方法載入
如:Dog dog = new Dog();
2、調(diào)用 Class.forName() 方法
通過反射加載類型,并創(chuàng)建對(duì)象實(shí)例
如:Class clazz = Class.forName(“Dog”);
Object dog =clazz.newInstance();
3、調(diào)用某個(gè) ClassLoader 實(shí)例的 loadClass() 方法
通過該 ClassLoader 實(shí)例的 loadClass() 方法載入。應(yīng)用程序可以通過繼承 ClassLoader 實(shí)現(xiàn)自己的類裝載器。
如:Class clazz = classLoader.loadClass(“Dog”);
Object dog =clazz.newInstance();
三者的區(qū)別:
1和2使用的類加載器是相同的,都是當(dāng)前類加載器。(即:this.getClass.getClassLoader)。3由用戶指定類加載器。如果需要在當(dāng)前類路徑以外尋找類,則只能采用第3種方式。第3種方式加載的類與當(dāng)前類分屬不同的命名空間。另外,1是靜態(tài)加載,2、3是動(dòng)態(tài)加載
兩個(gè)異常(exception)
靜態(tài)加載的時(shí)候如果在運(yùn)行環(huán)境中找不到要初始化的類,拋出的是NoClassDefFoundError,它在JAVA的異常體系中是一個(gè)Error
動(dòng)態(tài)加載的時(shí)候如果在運(yùn)行環(huán)境中找不到要初始化的類,拋出的是ClassNotFoundException,它在JAVA的異常體系中是一個(gè)checked異常
Class.forName與ClassLoader.loadClass區(qū)別
Class的裝載包括3個(gè)步驟:加載(loading),連接(link),初始化(initialize).
Class.forName(className)實(shí)際上是調(diào)用Class.forName(className, true, this.getClass().getClassLoader())。第二個(gè)參數(shù),是指Class被loading后是不是必須被初始化。
ClassLoader.loadClass(className)實(shí)際上調(diào)用的是ClassLoader.loadClass(name, false),第二個(gè)參數(shù)指Class是否被link。
Class.forName(className)裝載的class已經(jīng)被初始化,而ClassLoader.loadClass(className)裝載的class還沒有被link。一般情況下,這兩個(gè)方法效果一樣,都能裝載Class。但如果程序依賴于Class是否被初始化,就必須用Class.forName(name)了。
例如,在JDBC編程中,?吹竭@樣的用法,Class.forName("com.mysql.jdbc.Driver").
如果換成了getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行。
com.mysql.jdbc.Driver的源代碼如下:
Java代碼
// Register ourselves with the DriverManager
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
原來(lái),Driver在static塊中會(huì)注冊(cè)自己到java.sql.DriverManager。而static塊就是在Class的初始化中被執(zhí)行。