Java中我們一般會使用new關鍵字實例化對象然后調用該對象所屬類提供的方法來實現相應的功能,比如我們現在有個主類叫Web類這個類中能實現各種方法,比如用戶注冊、發送郵件等功能,代碼如下:
1 /* 2 * web功能實現類 3 */ 4 public class Web { 5 6 public static void main(String[] args) { 7 //每次有新功能都需要重新加載 8 if("UserReg".equals(args[0])) { 9 UserReg ur = new UserReg(); 10 ur.action(); 11 } 12 if("SendEmail".equals(args[0])) { 13 SendEmail se = new SendEmail(); 14 se.action(); 15 } 16 17 18 } 19 20 }
上面的代碼簡單的通過命令行的參數進行功能的調用,當然擴展到web的url參數原理也完全一樣,通過代碼可以看到,我們需要調用某一個功能,則必須實例化該功能所在的對象,並且每當添加一個新功能時,必須再寫一個if語句進行添加,並不能動態擴展;假設當我們只有UserReg類時,SendEmail類正在開發中,那么這兩個功能都是無法使用的,因為如果實例化一個不存在的類時編譯器會報錯,代碼根本無法通過編譯。這些所說的就是Java的靜態加載,靜態加載的含義就是在程序的編譯階段進行加載,當出現任何類不存在或者方法不存在的錯誤時,編譯都不通過,這就是Java中的靜態加載
那么與靜態加載相對應的動態加載的含義就是在程序運行時真正的執行代碼,編譯過程不進行任何檢查,這樣就避免了上面的問題,實現方式就是通過類的反射,我們改進上面的執行類為動態加載的,代碼如下:
1 /* 2 * web功能實現類 3 * 動態加載舉例 4 */ 5 public class Web { 6 7 public static void main(String[] args) { 8 try { 9 Class<?> w = Class.forName("net.zengzhiying.dynamicloading." + args[0]); 10 IWeb i = (IWeb) w.newInstance(); 11 i.action(); 12 } catch (ClassNotFoundException e) { 13 e.printStackTrace(); 14 } catch (InstantiationException e) { 15 e.printStackTrace(); 16 } catch (IllegalAccessException e) { 17 e.printStackTrace(); 18 } 19 } 20 21 }
上面代碼就是通過forName方法進行反射從而動態加載類,w就是對應類的類類型,同時也是Class的對象,所以從某種意義上來說,萬事萬物皆是對象,類也是對象,類對象和類的對象是嚴格區分的,類對象也就是類類型,那么使用類類型的newInstance方法可以創建該類類型的類的對象;另外為了解決每次實例化對象類都不同的問題,這里使用的父接口來統一聲明,我們需要任何功能只需要實現IWeb接口即可,不同功能模塊由不同的程序員實現也是沒問題的,或者使用父類或者抽象類來統一聲明,子類中進行方法的重寫或實現也可以,總之這個地方就是利用的多態的思想來實現,IWeb接口代碼如下:
1 public interface IWeb { 2 public void action(); 3 }
那么我們現在實現其中的模塊:
UserReg.java
1 public class UserReg implements IWeb { 2 3 public void action() { 4 System.out.println("我實現了用戶注冊的功能!"); 5 } 6 }
SendEmail.java
1 public class SendEmail implements IWeb { 2 public void action() { 3 System.out.println("我實現了發送電子郵件的功能"); 4 } 5 }
以上這些代碼通過編譯是沒有任何問題的,那么執行的時候我們使用命令行執行來傳參數,eclipse不能直接執行,效果如下:
通過執行可以看到,很容易的通過參數實現了不同的功能操作,對於不存在的功能,那么很顯然會拋出異常,因為編譯階段沒有經過嚴格的驗證,所以拋出異常也是必然的,實際開發中我們要進行恰當的異常處理,這樣就用動態加載實現了功能模塊的無限擴展,我們后來添加UserLogin用戶登錄模塊或者添加UserLogout用戶退出模塊,完全不必要修改Web主類中所有的代碼,只是都實現IWeb接口即可,這種動態加載類的思想在框架底層應用中也是經常用到的。