1. 程式人生 > >Class.forName與動態加載

Class.forName與動態加載

但是 size 存在 判斷 代碼 javac 解決 int ack

可以通過Class.forName("類的全類名")方法創建一個類的類類型。不僅如此,這個方法還表示了動態加載類。

動態加載類與靜態加載類的區分:

  • 編譯時刻加載的類稱為靜態加載類。
  • 運行時刻加載的類稱為動態加載類。

靜態加載的不足:在編譯時就會把所有類都加載,不論是否使用

Office.java類

 1 class Office{
 2     public static void main(String args[]){
 3             if("Word".equals(args[0])){
 4                 Word word=new Word();
5 word.start(); 6 } 7 if("Excel".equals(args[0])){ 8 Excel excel=new Excel(); 9 excel.start(); 10 } 11 } 12 }

思考:這個程序是否能夠通過編譯?

Office.java:4: 錯誤: 找不到符號
                                Word word=new Word();
                                ^
  符號:   類 Word
  位置: 類 Office
Office.java:4: 錯誤: 找不到符號
                                Word word=new Word();
                                              ^
  符號:   類 Word
  位置: 類 Office
Office.java:8: 錯誤: 找不到符號
                                Excel excel=new Excel();
                                ^
  符號:   類 Excel
  位置: 類 Office
Office.java:8: 錯誤: 找不到符號
                                Excel excel=new Excel();
                                                ^
  符號:   類 Excel
  位置: 類 Office
4 個錯誤

思考:毫無疑問肯定是編譯失敗的,因為Word、Excel類還沒有定義,當然也不存在兩個start()方法。正因為如此編譯失敗也就理所當然了,但是如果多考慮一點:Word用嗎?Excel用嗎?也許這兩個類與兩個方法都用不到,既然都不用,可是編譯卻無法通過。

Word.java:編寫Word類和start方法

1 class Word {
2     public void start(){
3         System.out.println("Word...starts..");
4     }
5 }

繼續編譯這個程序:現在只報了兩個關於Excel的錯誤。

 F:\xj>javac Word.java
 
 F:\xj>javac Office.java
 Office.java:8: 錯誤: 找不到符號
                                 Excel excel=new Excel();
                                 ^
   符號:   類 Excel
   位置: 類 Office
 Office.java:8: 錯誤: 找不到符號
                                 Excel excel=new Excel();
                                                 ^
   符號:   類 Excel
   位置: 類 Office
 2 個錯誤

思考:此刻再來思考和上面一樣的問題,如果只需要Word,不需要Excel,但是這個程序也依然運行不了。因為程序做的是靜態加載。即:new方式創建對象都是靜態加載類

使用靜態加載導致了不管這些類是否使用,在編譯的時候就必須加載所有可能使用到的類。

然而在實際中,希望Word存在,Word就可以用;當用Excel的時候java編譯器你再提醒我Excel有問題。就例如我們程序中有100個程序,但是只要是一個有了問題,其他的都用不了。其實這並不是我們想要看到的。這就是編譯時加載導致的。所以希望利用運行時動態加載來解決該問題。

動態加載

通過new方法來創建對象都是靜態加載,但是通過forName()方法去可以進行動態加載。

OfficeBetter.java:這裏采用動態加載

 1 class OfficeBetter{
 2     public static void main(String args[]){
 3         try{
 4             //動態加載類在運行時刻。編譯的時候並不會報錯,他才不會管你是哪個類呢。
 5             Class classWord=Class.forName(args[0]);
 6         }catch(Exception e){
 7             e.printStackTrace();
 8         }
 9     }
10 }

問題:接下來創建對象又有了問題了,如果這裏面使用Word word=(Word)classWord.newInstance(),此刻如果傳入的是Excel就出現問題了;如果往Excel做強制類型轉換,那麽如果傳入Word同樣會出現問題。

思路:所以這裏面要提升一下思想,給Word與Excel制定一個標準,然後讓Word與Excel實現這個標準OfficeAble。完整代碼如下:

OfficeBetter.java

 1 class OfficeBetter{
 2     public static void main(String args[]){
 3         try{
 4             Class class01=Class.forName(args[0]);        
 5             OfficeAble oa=(OfficeAble)class01.newInstance();
 6             oa.start();
 7         }catch(Exception e){
 8             e.printStackTrace();
 9         }
10     }
11     
12 }

OfficeAble.java:接口

1 interface OfficeAble{
2     public void start();
3 }

Word.java

1 class Word implements OfficeAble{
2     public void start(){
3         System.out.println("Word...starts..");
4     }
5 }

此刻編譯都是完全可以通過, 然後我們分別輸入Excel與word

F:\xj>java OfficeBetter Excel
java.lang.ClassNotFoundException: Excel
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Unknown Source)
        at OfficeBetter.main(OfficeBetter.java:5)

F:\xj>java OfficeBetter Word 

發現:當輸入Excel的時候才會發生錯誤,但是當輸入Word的時候完全可以使用。
和之前的相比,不同的是,這裏面編譯的時候沒有任何問題。word也可以正常使用。只有在輸入Excel,開始運行Excel的時候才會報錯——notFoundException。 這正是我們需要的動態加載:在編譯的時候不去理會,在使用的時候再去判斷。
接下來就可以創建對象了: 通過類類型創建該類的對象。

運行結果:

F:\xj>javac OfficeBetter.java
F:\xj>java OfficeBetter Word
Word...starts.. 


當然類似Word類,也可以建一個Excel類:

class Excel implements OfficeAble{
    public void start(){
    System.out.println("Excel...starts..");
    }
}


F:\xj>javac Excel.java
F:\xj>java OfficeBetter Excel
Excel...starts...

這裏面OfficeBetter這個類不用再編譯,直接運行就可以了

功能性的類一般使用動態加載,而不是靜態加載

END.

Class.forName與動態加載