作者:江南白衣
Java 5的泛型語(yǔ)法已經(jīng)有太多書(shū)講了,這里不再打字貼書(shū)。GP一定有用,不然Java和C#不會(huì )約好了似的同時(shí)開(kāi)始支持GP。但大家也清楚,GP和Ruby式的動(dòng)態(tài)OO語(yǔ)言屬于不同的意識形態(tài),如果是一人一票,我想大部分的平民程序員更熱衷動(dòng)態(tài)OO語(yǔ)言的平白自然。但如果不準備跳槽到支持JSR223的動(dòng)態(tài)語(yǔ)言,那還是看看GP吧。
胡亂總結泛型的四點(diǎn)作用:
第一是泛化,可以拿個(gè)T代表任意類(lèi)型。 但GP是被C++嚴苛的靜態(tài)性逼出來(lái)的,落到Java、C#這樣的花語(yǔ)平原里----所有對象除幾個(gè)原始類(lèi)型外都派生于Object,再加上Java的反射功能,Java的Collection庫沒(méi)有范型一樣過(guò)得好好的。
第二是泛型 + 反射,原本因為Java的泛型拿不到T.class而覺(jué)得泛型沒(méi)用,最近才剛剛學(xué)到通過(guò)反射的API來(lái)獲取T的Class,后述。
第三是收斂,就是增加了類(lèi)型安全,減少了強制類(lèi)型轉換的代碼。這點(diǎn)倒是Java Collection歷來(lái)的弱項。
第四是可以在編譯期搞很多東西,比如MetaProgramming。但除非能完全封閉于框架內部,框架的使用者和擴展者都不用學(xué)習這些東西的用法,否則那就是自絕于人民的票房毒藥。C++的MetaProgramming好厲害吧,但對比一下Python拿Meta Programming生造一個(gè)Class出來(lái)的簡(jiǎn)便語(yǔ)法,就明白什么才是真正的叫好又叫座。
所以,作為一個(gè)架構設計師,應該使用上述的第2,3項用法,在框架類(lèi)里配合使用反射和泛型,使得框架的能力更強; 同時(shí)采用收斂特性,本著(zhù)對人民負責的精神,用泛型使框架更加類(lèi)型安全,更少強制類(lèi)型轉換。
擦拭法避免了Java的流血分裂 :
大家經(jīng)常罵Java GP的擦拭法實(shí)現,但我覺(jué)得多虧于它的中庸特性---如果你用就是范型,不用就是普通Object,避免了Java陣營(yíng)又要經(jīng)歷一場(chǎng)to be or not to be的分裂。
最大的例子莫過(guò)Java 5的Collection 框架, 比如有些同學(xué)堅持認為自己不會(huì )白癡到類(lèi)型出錯,而且難以忍受每個(gè)定義的地方都要帶一個(gè)泛型定義List〈Book〉,不用強制類(lèi)型轉換所省下的代碼還不夠N處定義花的(對了,java里面還沒(méi)有tyepdef.....),因此對范型十分不感冒,這時(shí)就要齊齊感謝這個(gè)搽拭法讓你依然可以對一個(gè)泛型框架保持非泛型的用法了...
通過(guò)反射獲得 T.class:
不知為何書(shū)上不怎么講這個(gè),是差沙告訴我才知道的,最經(jīng)典的應用見(jiàn)Hibernate wiki的Generic Data Access Objects, 代碼如下:
精華就是這句了:
泛型之后,所有BaseHibernateEntityDao的子類(lèi)只要定義了泛型,就無(wú)需再重載getEnttityClass(),get()函數和find()函數,銷(xiāo)益挺明顯的,所以SpringSide的Dao基類(lèi)毫不猶豫就泛型了。
不過(guò)擦拭法的大棒仍在,所以子類(lèi)的泛型語(yǔ)法可不能亂寫(xiě),最正確的用法只有:
Java 5的泛型語(yǔ)法已經(jīng)有太多書(shū)講了,這里不再打字貼書(shū)。GP一定有用,不然Java和C#不會(huì )約好了似的同時(shí)開(kāi)始支持GP。但大家也清楚,GP和Ruby式的動(dòng)態(tài)OO語(yǔ)言屬于不同的意識形態(tài),如果是一人一票,我想大部分的平民程序員更熱衷動(dòng)態(tài)OO語(yǔ)言的平白自然。但如果不準備跳槽到支持JSR223的動(dòng)態(tài)語(yǔ)言,那還是看看GP吧。
胡亂總結泛型的四點(diǎn)作用:
第一是泛化,可以拿個(gè)T代表任意類(lèi)型。 但GP是被C++嚴苛的靜態(tài)性逼出來(lái)的,落到Java、C#這樣的花語(yǔ)平原里----所有對象除幾個(gè)原始類(lèi)型外都派生于Object,再加上Java的反射功能,Java的Collection庫沒(méi)有范型一樣過(guò)得好好的。
第二是泛型 + 反射,原本因為Java的泛型拿不到T.class而覺(jué)得泛型沒(méi)用,最近才剛剛學(xué)到通過(guò)反射的API來(lái)獲取T的Class,后述。
第三是收斂,就是增加了類(lèi)型安全,減少了強制類(lèi)型轉換的代碼。這點(diǎn)倒是Java Collection歷來(lái)的弱項。
第四是可以在編譯期搞很多東西,比如MetaProgramming。但除非能完全封閉于框架內部,框架的使用者和擴展者都不用學(xué)習這些東西的用法,否則那就是自絕于人民的票房毒藥。C++的MetaProgramming好厲害吧,但對比一下Python拿Meta Programming生造一個(gè)Class出來(lái)的簡(jiǎn)便語(yǔ)法,就明白什么才是真正的叫好又叫座。
所以,作為一個(gè)架構設計師,應該使用上述的第2,3項用法,在框架類(lèi)里配合使用反射和泛型,使得框架的能力更強; 同時(shí)采用收斂特性,本著(zhù)對人民負責的精神,用泛型使框架更加類(lèi)型安全,更少強制類(lèi)型轉換。
擦拭法避免了Java的流血分裂 :
大家經(jīng)常罵Java GP的擦拭法實(shí)現,但我覺(jué)得多虧于它的中庸特性---如果你用就是范型,不用就是普通Object,避免了Java陣營(yíng)又要經(jīng)歷一場(chǎng)to be or not to be的分裂。
最大的例子莫過(guò)Java 5的Collection 框架, 比如有些同學(xué)堅持認為自己不會(huì )白癡到類(lèi)型出錯,而且難以忍受每個(gè)定義的地方都要帶一個(gè)泛型定義List〈Book〉
通過(guò)反射獲得 T.class:
不知為何書(shū)上不怎么講這個(gè),是差沙告訴我才知道的,最經(jīng)典的應用見(jiàn)Hibernate wiki的Generic Data Access Objects, 代碼如下:
abstract public class BaseHibernateEntityDao<T> extends HibernateDaoSupport {
private Class<T> entityClass;
public BaseHibernateEntityDao() {
entityClass =(Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public T get(Serializable id) {
T o = (T) getHibernateTemplate().get(entityClass, id);
}
}
private Class<T> entityClass;
public BaseHibernateEntityDao() {
entityClass =(Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public T get(Serializable id) {
T o = (T) getHibernateTemplate().get(entityClass, id);
}
}
精華就是這句了:
Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
泛型之后,所有BaseHibernateEntityDao的子類(lèi)只要定義了泛型,就無(wú)需再重載getEnttityClass(),get()函數和find()函數,銷(xiāo)益挺明顯的,所以SpringSide的Dao基類(lèi)毫不猶豫就泛型了。
不過(guò)擦拭法的大棒仍在,所以子類(lèi)的泛型語(yǔ)法可不能亂寫(xiě),最正確的用法只有:
public class BookDao extends BaseHibernateEntityDao<Book>

