過去曾經(jīng)有很長一段時間,直至現(xiàn)在,存在這樣的一種觀點(diǎn),就是C#比Java的實(shí)現(xiàn)更漂亮。《Think in java》的作者Bruce Eckel曾經(jīng)公開質(zhì)疑過Java 5提供的泛型。
在C# 2.0支持泛型,而且在虛擬機(jī)級別支持,一開始接觸時,感覺是很震撼的,感覺到泛型從此走入主流應(yīng)用開發(fā)了。和C++相比,沒有C++模板那樣強(qiáng)的功能,完全做不到產(chǎn)生式編程的效果,也做不到編譯期計算的效果,但是它簡單實(shí)用。
Java 5也開始支持泛型,而且最終正式發(fā)行比C# 2.0要早,我之前就使用過Beta版本C#的泛型,也熟悉C++的模板語法,可能是內(nèi)心的傲慢,或者是懶惰,開始時只是將就著按照傳統(tǒng)的經(jīng)驗使用Java 5提供的泛型。
對事物的一知半解總是令人困擾的,在閱讀分析JDK源碼時,總會遇到一些Java 5額外提供的泛型用法,一開始忽略不計,但是看多了總會注意到的。
例如java.util.Collections類中的sort方法和binarySearch方法的接口:
public static < T>void sort(List< T>list, Comparator< ? super T>c);
public static < T>int binarySearch(List< ?
extends Comparable< ? super T>>list, T key);
extends和super這兩個關(guān)鍵字是C#和C++的泛型中都沒有的,為什么需要這樣的功能呢?
例如如下情形:
class A { }
class B extends A {}
void addAll(List< A> items) {}
如下代碼:
List< A> aList = ;
List< B> bList = ;
addAll(aList); //可以
addAll(bList); //編譯不通過
addAll(bList)是無法編譯通過的,
這一點(diǎn)在Java、C#、C++中都是如此,怎么辦呢?
在java中如下處理,修改addAll的接口,改為:
void addAll(List< ? extends A>items) {}
這樣,addAll(aList)和addAll(bList)都能夠編譯通過了。
另外super關(guān)鍵在算法中更是好用,如上面介紹的Collections.sort方法??荚?大提示如果你想在C#中實(shí)現(xiàn)一個和java.util.Collections.sort一樣的方法,你會發(fā)現(xiàn)那是做不到的!
為什么C#和C++無法提供這樣的功能呢?因為C#和C++都是運(yùn)行時的泛型支持,bList和aList的類型是不一樣的,List< A>和List< B>的實(shí)際類型都是不一樣的,運(yùn)行時對泛型的支持目前還無法象處理數(shù)組參數(shù)那樣具備協(xié)變能力。而Java的實(shí)現(xiàn)是編譯器的特性,這樣做的缺點(diǎn)就是性能沒有得到提升,但是可以提供更好的語法糖。
想起ajoo以前發(fā)表的一個觀點(diǎn),就是在應(yīng)用開發(fā)中,泛型提供的關(guān)鍵是類型安全,性能反而是其次。我對此十分認(rèn)同,重新審視java的泛型,我們會發(fā)現(xiàn)其設(shè)計頗具創(chuàng)新,而且向后兼容良好!
在C# 2.0支持泛型,而且在虛擬機(jī)級別支持,一開始接觸時,感覺是很震撼的,感覺到泛型從此走入主流應(yīng)用開發(fā)了。和C++相比,沒有C++模板那樣強(qiáng)的功能,完全做不到產(chǎn)生式編程的效果,也做不到編譯期計算的效果,但是它簡單實(shí)用。
Java 5也開始支持泛型,而且最終正式發(fā)行比C# 2.0要早,我之前就使用過Beta版本C#的泛型,也熟悉C++的模板語法,可能是內(nèi)心的傲慢,或者是懶惰,開始時只是將就著按照傳統(tǒng)的經(jīng)驗使用Java 5提供的泛型。
對事物的一知半解總是令人困擾的,在閱讀分析JDK源碼時,總會遇到一些Java 5額外提供的泛型用法,一開始忽略不計,但是看多了總會注意到的。
例如java.util.Collections類中的sort方法和binarySearch方法的接口:
public static < T>void sort(List< T>list, Comparator< ? super T>c);
public static < T>int binarySearch(List< ?
extends Comparable< ? super T>>list, T key);
extends和super這兩個關(guān)鍵字是C#和C++的泛型中都沒有的,為什么需要這樣的功能呢?
例如如下情形:
class A { }
class B extends A {}
void addAll(List< A> items) {}
如下代碼:
List< A> aList = ;
List< B> bList = ;
addAll(aList); //可以
addAll(bList); //編譯不通過
addAll(bList)是無法編譯通過的,
這一點(diǎn)在Java、C#、C++中都是如此,怎么辦呢?
在java中如下處理,修改addAll的接口,改為:
void addAll(List< ? extends A>items) {}
這樣,addAll(aList)和addAll(bList)都能夠編譯通過了。
另外super關(guān)鍵在算法中更是好用,如上面介紹的Collections.sort方法??荚?大提示如果你想在C#中實(shí)現(xiàn)一個和java.util.Collections.sort一樣的方法,你會發(fā)現(xiàn)那是做不到的!
為什么C#和C++無法提供這樣的功能呢?因為C#和C++都是運(yùn)行時的泛型支持,bList和aList的類型是不一樣的,List< A>和List< B>的實(shí)際類型都是不一樣的,運(yùn)行時對泛型的支持目前還無法象處理數(shù)組參數(shù)那樣具備協(xié)變能力。而Java的實(shí)現(xiàn)是編譯器的特性,這樣做的缺點(diǎn)就是性能沒有得到提升,但是可以提供更好的語法糖。
想起ajoo以前發(fā)表的一個觀點(diǎn),就是在應(yīng)用開發(fā)中,泛型提供的關(guān)鍵是類型安全,性能反而是其次。我對此十分認(rèn)同,重新審視java的泛型,我們會發(fā)現(xiàn)其設(shè)計頗具創(chuàng)新,而且向后兼容良好!