作者:江南白衣?
?? Java 5的泛型語法已經有太多書講了,這里不再打字貼書。GP一定有用,不然Java和C#不會約好了似的同時開始支持GP。但大家也清楚,GP和Ruby式的動態OO語言屬于不同的意識形態,如果是一人一票,我想大部分的平民程序員更熱衷動態OO語言的平白自然。但如果不準備跳槽到支持JSR223的動態語言,那還是看看GP吧。
?? 胡亂總結泛型的四點作用:
?? 第一是泛化,可以拿個T代表任意類型。 但GP是被C++嚴苛的靜態性逼出來的,落到Java、C#這樣的花語平原里----所有對象除幾個原始類型外都派生于Object,再加上Java的反射功能,Java的Collection庫沒有范型一樣過得好好的。
???第二是泛型 +?反射,原本因為Java的泛型拿不到T.class而覺得泛型沒用,最近才剛剛學到通過反射的API來獲取T的Class,后述。
?? 第三是收斂,就是增加了類型安全,減少了強制類型轉換的代碼。這點倒是Java Collection歷來的弱項。
?? 第四是可以在編譯期搞很多東西,比如MetaProgramming。但除非能完全封閉于框架內部,框架的使用者和擴展者都不用學習這些東西的用法,否則那就是自絕于人民的票房毒藥。C++的MetaProgramming好厲害吧,但對比一下Python拿Meta Programming生造一個Class出來的簡便語法,就明白什么才是真正的叫好又叫座。
???所以,作為一個架構設計師,應該使用上述的第2,3項用法,在框架類里配合使用反射和泛型,使得框架的能力更強; 同時采用收斂特性,本著對人民負責的精神,用泛型使框架更加類型安全,更少強制類型轉換。
???
?? 擦拭法避免了Java的流血分裂?:
??? 大家經常罵Java GP的擦拭法實現,但我覺得多虧于它的中庸特性---如果你用就是范型,不用就是普通Object,避免了Java陣營又要經歷一場to be or not to be的分裂。?
?? ?最大的例子莫過Java 5的Collection 框架,?比如有些同學堅持認為自己不會白癡到類型出錯,而且難以忍受每個定義的地方都要帶一個泛型定義List〈Book〉,不用強制類型轉換所省下的代碼還不夠N處定義花的(對了,java里面還沒有tyepdef.....),因此對范型十分不感冒,這時就要齊齊感謝這個搽拭法讓你依然可以對一個泛型框架保持非泛型的用法了...
?? 通過反射獲得 T.class:
???
??? 不知為何書上不怎么講這個,是差沙告訴我才知道的,最經典的應用見Hibernate wiki的Generic Data Access Objects, 代碼如下:?
? 精華就是這句了:
? 泛型之后,所有BaseHibernateEntityDao的子類只要定義了泛型,就無需再重載getEnttityClass(),get()函數和find()函數,銷益挺明顯的,所以SpringSide的Dao基類毫不猶豫就泛型了。
? 不過擦拭法的大棒仍在,所以子類的泛型語法可不能亂寫,最正確的用法只有:
???
?? Java 5的泛型語法已經有太多書講了,這里不再打字貼書。GP一定有用,不然Java和C#不會約好了似的同時開始支持GP。但大家也清楚,GP和Ruby式的動態OO語言屬于不同的意識形態,如果是一人一票,我想大部分的平民程序員更熱衷動態OO語言的平白自然。但如果不準備跳槽到支持JSR223的動態語言,那還是看看GP吧。
?? 胡亂總結泛型的四點作用:
?? 第一是泛化,可以拿個T代表任意類型。 但GP是被C++嚴苛的靜態性逼出來的,落到Java、C#這樣的花語平原里----所有對象除幾個原始類型外都派生于Object,再加上Java的反射功能,Java的Collection庫沒有范型一樣過得好好的。
???第二是泛型 +?反射,原本因為Java的泛型拿不到T.class而覺得泛型沒用,最近才剛剛學到通過反射的API來獲取T的Class,后述。
?? 第三是收斂,就是增加了類型安全,減少了強制類型轉換的代碼。這點倒是Java Collection歷來的弱項。
?? 第四是可以在編譯期搞很多東西,比如MetaProgramming。但除非能完全封閉于框架內部,框架的使用者和擴展者都不用學習這些東西的用法,否則那就是自絕于人民的票房毒藥。C++的MetaProgramming好厲害吧,但對比一下Python拿Meta Programming生造一個Class出來的簡便語法,就明白什么才是真正的叫好又叫座。
???所以,作為一個架構設計師,應該使用上述的第2,3項用法,在框架類里配合使用反射和泛型,使得框架的能力更強; 同時采用收斂特性,本著對人民負責的精神,用泛型使框架更加類型安全,更少強制類型轉換。
???
?? 擦拭法避免了Java的流血分裂?:
??? 大家經常罵Java GP的擦拭法實現,但我覺得多虧于它的中庸特性---如果你用就是范型,不用就是普通Object,避免了Java陣營又要經歷一場to be or not to be的分裂。?
?? ?最大的例子莫過Java 5的Collection 框架,?比如有些同學堅持認為自己不會白癡到類型出錯,而且難以忍受每個定義的地方都要帶一個泛型定義List〈Book〉
?? 通過反射獲得 T.class:
???
??? 不知為何書上不怎么講這個,是差沙告訴我才知道的,最經典的應用見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的子類只要定義了泛型,就無需再重載getEnttityClass(),get()函數和find()函數,銷益挺明顯的,所以SpringSide的Dao基類毫不猶豫就泛型了。
? 不過擦拭法的大棒仍在,所以子類的泛型語法可不能亂寫,最正確的用法只有:
???
public?class?BookDao?extends?BaseHibernateEntityDao<Book>
?
http://www.javaspecialists.co.za/archive/newsletter.do?issue=123&locale=en_US
貼一篇用泛型的方式實現策略模式...
how about this?
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import junit.framework.TestCase;
class TClass<T> {
}
class GoodClass<T> extends TClass<String> {
public ParameterizedType getClassT() {
return (ParameterizedType) getClass().getGenericSuperclass();
}
}
class BadClass<T> extends TClass<T> {
public ParameterizedType getClassT() {
return (ParameterizedType) getClass().getGenericSuperclass();
}
}
public class GenericsTest extends TestCase {
private void print(Type[] targs) {
System.out.print("actual type arguments are:");
for (int j = 0; j < targs.length; j++) {
System.out.print(" instance of " + targs[j].getClass().getName() + ":");
System.out.println(" (" + targs[j] + ")");
}
}
public void testGoodClass() throws Exception {
ParameterizedType type = new GoodClass<String>().getClassT();
Type[] types = type.getActualTypeArguments();
print(types);
assertEquals(TClass.class, type.getRawType());
assertEquals(String.class, types[0]);
}
public void testBadClass() throws Exception {
ParameterizedType type = new BadClass<String>().getClassT();
Type[] types = type.getActualTypeArguments();
print(types);
assertEquals(TClass.class, type.getRawType());
assertEquals(String.class, types[0]);
}
}
剛才試驗了一下Generic無法獲取自己的Generic Type類型,后來仔細看了下擦拭法的本意。實際上BadClass<String>()實例化以后Class里面就不包括T的信息了,對于Class而言T已經被擦拭為Object,而真正的T參數被轉到使用T的方法(或者變量聲明或者其它使用T的地方)里面(如果沒有那就沒有存根),所以無法反射到T的具體類別,也就無法得到T.class。而getGenericSuperclass()是Generic繼承的特例,對于這種情況子類會保存父類的Generic參數類型,返回一個ParameterizedType,這時可以獲取到父類的T.class了,這也正是子類確定應該繼承什么T的方法。
之前要重載getEntityClass函數,而且find單體的函數如get(id) 也要重載做類型轉換.
http://www-128.ibm.com/developerworks/java/library/j-genericdao.html
里面那介紹的方式雖然真正實用性不高,但是很好的用Interface+AOP實現Java版的仿Ruby的mixin的思路演示
java綜合網
不錯,不錯~~~
public class Convertor<From, To>
{
public To convert(From from)
{
To to;
// 初始化to的值
return to;
}
}
Convertor<Type1, Type2> cntr = new Convertor<Type1, Type2>();
Type2 t2 = cntr.convert(t1);
還是無法用博主說的方式來實現。
public class Foo<C,T>
{
...
public <T>T cover(C c)
{
...
}
Foo<Type1, Type2> foo = new Foo<Type1, Type2>();
Type2 t2 = cntr.convert(t1);
...
}