Posted on 2005-08-09 09:36
laogao 閱讀(5172)
評論(3) 編輯 收藏 所屬分類:
On Java
最近看到BlogJava上有人在討論為什么Java范型不支持數組http://www.tkk7.com/myqiao/archive/2005/08/08/9580.html
我想這個問題的答案是:因為這樣做會破壞類型安全。核心的問題在于Java范型和C#范型存在根本區別:Java的范型停留在編譯這一層,到了運行時,這些范型的信息其實是被抹掉的;而C#的范型做到了MSIL這一層。Java的做法不必修改JVM,減少了潛在的大幅改動和隨之而來的風險,也許同時也反映出Java Bytecode規范在設計之初的先天不足;C#則大刀闊斧,連CLR一起改以支持更徹底的范型,換句話說,在范型這一點上,感覺C#更C++一點。
在Java中,Object[]數組可以是任何數組的父類,或者說,任何一個數組都可以向上轉型成它在定義時指定元素類型的父類的數組,這個時候如果我們往里面放不同于原始數據類型 但是滿足后來使用的父類類型的話,編譯不會有問題,但是在運行時會檢查加入數組的對象的類型,于是會拋ArrayStoreException:
String[] strArray = new String[20];
Object[] objArray = strArray;
objArray[0] = new Integer(1); // throws ArrayStoreException at runtime
因為Java的范型會在編譯后將類型信息抹掉,這樣如果Java允許我們使用類似
Map<Integer, String>[] mapArray = new Map<Integer, String>[20];
這樣的語句的話,我們在隨后的代碼中可以把它轉型為Object[]然后往里面放Map<Double, String>實例。這樣做不但編譯器不能發現類型錯誤,就連運行時的數組存儲檢查對它也無能為力,它能看到的是我們往里面放Map的對象,我們定義的<Integer, String>在這個時候已經被抹掉了,于是而對它而言,只要是Map,都是合法的。想想看,我們本來定義的是裝Map<Integer, String>的數組,結果我們卻可以往里面放任何Map,接下來如果有代碼試圖按原有的定義去取值,后果是什么不言自明。
所以,Java編譯器不允許我們new范型數組。