|
|
在一些應用中,無法事先知道使用者將載入什麼類別(例如載入JDBC驅動程式),而必須讓使用者指定類別名稱以載入類別。你可以使用Class的靜態forName()方法實現動態加載類別,以下是個簡單示範,可以指定類別名稱來獲得類別的相關資訊: try { Class c = Class.forName(args[0]); System.out.println("類別名稱:" + c.getName()); System.out.println("是否為介面:" + c.isInterface()); System.out.println("是否為基本型態:" + c.isPrimitive()); System.out.println("是否為陣列:" + c.isArray()); System.out.println("父類別:" + c.getSuperclass().getName()); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("沒有指定類別名稱"); } catch(ClassNotFoundException e) { System.out.println("找不到指定的類別"); } 在 指定類別給forName()方法後,如果找不到指定的類別,會丟出ClassNotFoundException例外。Class的靜態forName ()方法有兩個版本,另一個版本可以讓您指定類別名稱、載入類別時是否執行靜態區塊、指定類別載入器(Class loader): static Class forName(String name, boolean initialize, ClassLoader loader) 之前曾經說過,預設上在載入類別的時候,如果類別中有定義靜態區塊則會執行它,你可以使用forName()的第二個版本,將initialize設定為false,如此在載入類別時並不會馬上執行靜態區塊,而會在使用類別建立物件時才執行靜態區塊,為了印證,你可以先設計一個測試類別。 package cc.openhome; public class Some { static { System.out.println("[執行靜態區塊]"); } } 範例只定義了靜態區塊顯示一段訊息,以觀察靜態區塊何時被執行,如果用第一個版本的forName()方法: try { System.out.println("載入cc.openhome.Some"); Class c = Class.forName("cc.openhome.Some"); System.out.println("使用cc.openhome.Some宣告參考名稱"); Some test = null; System.out.println("使用cc.openhome.Some建 立物件"); test = new Some(); } catch(ClassNotFoundException e) { System.out.println("找不到指定的類別"); } 從執行結果中你會看到,第一個版本的forName()方法在載入類別之後,預設會馬上執行靜態區塊。如果用第二個版本的forName()方法: try { System.out.println("載入cc.openhome.Some"); Class c = Class.forName("cc.openhome.Some", false, // 載入類別時不執行靜態方法 Thread.currentThread().getContextClassLoader()); System.out.println("使用cc.openhome.Some宣告參考名稱"); Some test = null; System.out.println("使用cc.openhome.Some建 立物件"); test = new Some(); } catch(ClassNotFoundException e) { System.out.println("找不到指定的類別"); } 由 於使用第二個版本的forName()方法時,設定initialize為false,所以載入類別時並不會馬上執行靜態區塊,而會在使用類別建立物件時 才去執行靜態區塊,第二個版本的forName()方法會需要一個 類別載入器(Class loader),範例中所使用的是主執行緒的環境類別載入器(Context Class Loader)。 事實上如果使用第一個版本的forName()方法,等同於: Class.forName(className, true, currentLoader);
其中currentLoader是目前類別的類別載入器,也就是如果你在A類別中使用Class.forName()第一個版本,預設就是用A類別的類別載入器來載入類別。 |