Class.forName與動態加載
可以通過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與動態加載