讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議105:動態加載不適合數組 >

建議105:動態加載不適合數組

上一個建議解釋了為什麼要使用forName,本建議就來說說哪些地方不適合使用動態加載。如果forName要加載一個類,那它首先必須是一個類——8個基本類型排除在外,它們不是一個具體的類;其次,它必須具有可追索的類路徑,否則就會報ClassNotFoundException。

在Java中,數組是一個非常特殊的類,雖然它是一個類,但沒有定義類路徑,例如這樣的代碼:


public static void main(Stringargs)throws Exception{

Stringstrs=new String[10];

Class.forName("java.lang.String");

}


String是一個類型聲明,它作為forName的參數應該也是可行的吧!但是非常遺憾,其運行結果如下:


Exception in thread"main"java.lang.ClassNotFoundException:java/lang/String

at java.lang.Class.forName0(Native Method)

at java.lang.Class.forName(Class.java:169)

at Client.main(Client.java:6)


產生ClassNotFoundException異常的原因是數組雖然是一個類,在聲明時可以定義為String,但編譯器編譯後會為不同的數組類型生成不同的類,具體如表7-2所示。

在編碼期,我們可以聲明一個變量為String,但是經過編譯器編譯後就成為了[Ljava.lang.String。明白了這一點,再根據以上的表格可知,動態加載一個對像數組只要加載編譯後的數組對象就可以了,代碼如下:


//加載一個String數組

Class.forName("[Ljava.lang.String;");

//加載一個long數組

Class.forName("[J");


雖然以上代碼可以動態加載一個數組類,但是這沒有任何意義,因為它不能生成一個數組對象,也就是說以上代碼只是把一個String類型的數組類和long類型的數組類加載到了內存中(如果內存中沒有該類的話),並不能通過newInstance方法生成一個實例對象,因為它沒有定義數組的長度,在Java中數組是定長的,沒有長度的數組是不允許存在的。

既然反射不能定義一個數組,那問題就來了:如何動態加載一個數組呢?比如依據輸入動態產生一個數組。其實可以使用Array數組反射類來動態加載,代碼如下:


//動態創建數組

Stringstrs=(String)Array.newInstance(String.class,8);

//創建一個多維數組

intints=(int)Array.newInstance(int.class,2,3);


因為數組比較特殊,要想動態創建和訪問數組,基本的反射是無法實現的,「上帝對你關閉一扇門,同時會為你打開另外一扇窗」,於是Java就專門定義了一個Array數組反射工具類來實現動態探知數組的功能。

注意 通過反射操作數組使用Array類,不要採用通用的反射處理API。