Java爲什麼不支持泛型的數組的緣由

泛型數組實際上是挺嚴謹的,說白了就是在「編譯的時候經過增長強制類型轉換的代碼,來避免用戶編寫出可能引起ClassCastException的代碼」。這其實也算是Java引入泛型的一個目的。可是,一個頗具諷刺意味的問題出現了:若是容許了泛型數組,那麼編譯器添加的強制類型轉換的代碼就會有多是錯誤的。程序員

看下面的例子:
//下面的代碼使用了泛型的數組,是沒法經過編譯的
GenTest<String> genArr[] = new GenTest<String>[2];
Object[] test = genArr;
GenTest<StringBuffer> strBuf = new GenTest<StringBuffer>();
strBuf.setValue(new StringBuffer());
test[0] = strBuf;
GenTest<String> ref = genArr[0]; //上面兩行至關於使用數組移花接木,讓Java編譯器把GenTest<StringBuffer>看成了GenTest<String>
String value = ref.getValue();// 這裏是重點!數組

上面的代碼中,最後一行是重點。根據本文第一部分的介紹,「String value = ref.getValue()」會被替換成「String value =(String)ref.getValue()」。固然咱們知道,ref其實是指向一個存儲着StringBuffer對象的GenTest對象。因此,編譯器生成出來的代碼是隱含着錯誤的,在運的時候就會拋出ClassCastException。
可是,若是沒有「String value = ref.getValue();」這行代碼,那麼程序能夠說沒有任何錯誤。這全都是Java中多態的功勞。咱們來分析一下,對於上面代碼中建立出來的GenTest對象,其實不管value引用實際指向的是什麼對象,對於類中的代碼來講都是沒有任何影響的——由於在GenTest類中,這個對象僅僅會被看成是基類型的對象(在這裏也就是Object的對象)來使用。因此,不管是String的對象,仍是StringBuffer的對象,都不可能引起任何問題。舉例來講,若是調用valued的hashcode方法,那麼,若是value指向的是String的對象,實際執行的就是String類中的hashcode方法,若是是StringBuffer的對象,那麼實際執行的就是StringBuffer類中的hashcode方法。
從這裏能夠看出,即便支持泛型數組也不會帶來什麼災難性的後果,最多就是可能引起ClassCastException。並且平心而論,這個仍是程序員本身的錯誤,實在算不得是Java編譯器的錯誤。可是從另外一個角度看,這確實是個巨大的諷刺:泛型是爲了消滅ClassCastException而出現的,可是在這個時候它本身卻引起了ClassCastException。我們中國人把這個叫作搬起石頭砸本身的腳。
固然制定JSR的那幫子人可能沒學過中文,可是他們確定是發現了這個令他們糾結的問題。被標榜爲Java 5重要feature的泛型居然陷入了這麼一個怪圈。因而,他們在某個月黑風高的晚上,在某個角落的會議室內,悄悄的決定一不作二不休——不支持泛型的數組了。
 code

相關文章
相關標籤/搜索