天堂的另一角

天堂魷魚的原创技术博客。所謂兼容並包,無奇不有。

 

Java中無恥的範型實現

一直聽說Java中的範型實現得很糟糕,但自己雖然一直用,卻也沒覺得有何問題,感覺比起遍地氾濫的Object來說,還是要優雅多了。然而,這不過是錯覺罷了。

Anders hejlsberg 解釋過這一現象: Java的泛型最初是基於Martin Odersky和其它人一起做的稱作Pizza的一個項目的。Pizza後改名為GJ,然後成為JSR,最後以被Java語言收容而告終。這種泛型以能夠 在原有的VM(Virtual Machine,虛擬機)上運行為關鍵設計目標。也就是說,你不必修改你的VM,但它會帶來很多限制。這些限制並不會很快出現,但很快你就會說:「嗯,這 有點陌生。」

對於我來說,事情的起因是前陣子需要寫一個循環隊列充當Buffer用,空間是有限的,但可以無限次的循環再利用。要求資源佔用要小,性能要好。該隊列一開始就要將空間中的所有元素都初始化,所以類似刪除、空隊列判斷、隊列大小計算等常見操作都可以忽略,算是個比較好寫的數據結構。JDK中自然是沒有現成的類可用,AbstractList都顯得有些多餘,於是,我單純的創建了一個類CircularArrayList<E>,並指定實現接口List<E>。因為只需有限空間,為減小不必要的資源佔用,內部使用了普通的定長數組。注意,我按照以往的習慣,使用了範型,拉開了惡夢的序幕。

首先讓我崩潰的是這句語句:

E[] elementData = new E[capacity];

這是關於Java範型中最經典、也是最無奈的「錯誤」了。當時鬱悶的我上網一搜,發現了無數的「同道」。這種寫法,對於任何一個熟悉傳統範型的人來說,都不會覺得有何不妥吧。更雷人的是,網上查到這句語句的正確Java版寫法竟然是:

E[] elementData = (E[]) new Object[capacity];

我的天!那我要那個E是來幹嘛的?那直接用Object不就得了?當擺設啊?我不服氣,決心尋求「官方寫法」,打開我以往的最愛ArrayList<E>看其構造函數,赫然是:

this.elementData = (E[])new Object[initialCapacity];

我無語了。原來Java中的範型真的只是擺設。我的初始化的設想自然也完蛋了,因為你根本別想指望建立一個E的實例。以下語句在Java中也是無法編譯的:

for (int i = 0; i < size; i++) {
    elementData[convert(i)] 
== new E();
}

想知道「正確」寫法?說實話,實在太噁心了,我原本不想說的:

public void init(Class<E> c) {
    
for (int i = 0; i < size; i++) {
        elementData[convert(i)] 
== c.newInstance();
    }
}

這還是你走運的情況下。假如你的E不幸沒有缺省構造函數,你只能使用反射的方法,那個代碼更噁心,有興趣的自己看吧:http://serdom.eu/ser/2007/03/25/java-generics-instantiating-objects-of-type-parameter-without-using-class-literal

Anders hejlsberg 說道: 當你編譯一個Java泛型類時,編譯器會將所有的類型參數替換為Object。當然,如果你嘗試建立一個List,你就需要對所有的int進行裝箱。因此,這會有很大的開銷。另外,為了讓VM高興,編譯器必須為所有的類型插入類型轉換。如果一個List是Object的,而你想將這些Object視為Customer,就必須將 Object轉換為Customer,以讓類型檢查器滿意。而它在實現這些的時候,真的只是為你插入所有這些類型轉換。因此,你只是嘗到了語法上的甜頭,卻沒有獲得任何執行效率。所以我覺得這是(泛型的)Java實現的頭號問題。

這就是Java為了兼容性做出的折衷:以一種近乎無恥的方式,實現了一種現代編程語言中絕無僅有的「範型」。據說Java 7中會有真正的範型,在那之前,我想我還是不要再碰這個「極品」比較好。請.Net的程序員盡情的嘲笑我吧。也許我的下一個程序會是用python寫的吧。

posted on 2009-08-30 09:20 Addone 阅读(645) 评论(3)  编辑 收藏 引用 所属分类: 软件开发

评论

# re: Java中無恥的範型實現 2009-08-30 12:06 OwnWaterloo

You got it~~~  回复  更多评论   

# re: Java中無恥的範型實現 2009-09-06 19:17 罗莱家纺

阿道夫撒旦法  回复  更多评论   

# re: Java中無恥的範型實現 2009-10-08 11:13 Mfox

嘲笑?为什么要嘲笑。。。这不过是JAVA为了商业上的考虑,想出的权宜之计而已。。既然JAVA7里会有真正的范型,那也就没什么了。。。反正两种语言最后会变的越来越相似。。

  回复  更多评论   

只有注册用户登录后才能发表评论。

导航

统计

公告


Addone,又名:天堂鱿鱼。
这里是我的技术博客。其他文章
作为“杂感”分类存档。
我的新思想主要发往新站:
幻想园
幻想园

欢迎光临

Linux注册用户

feedsky
抓虾
google reader
bloglines

联系方式




My status

常用链接

留言簿(11)

随笔分类(99)

随笔档案(69)

相册

友情链接

推荐站点

搜索

积分与排名

最新评论

阅读排行榜