Java泛型的運用Java泛型的運用 說來慚愧,jdk1.6都快出來了,1.5的泛型還沒怎么用過。頂多用用List<Person>搭配foreach語法來簡化一些代碼。前段時間發(fā)現(xiàn)在設(shè)計Base類的時候發(fā)現(xiàn)不用泛型就免不了Object的轉(zhuǎn)型,相當不爽。前不久在江南白衣的blog上面看了獲取T.class的方法,收益匪淺。 下面說幾個泛型使用時注意的問題。 對于public void demo1(List<Object>list)這個接口,我可以這樣使用嗎? List<Person> personList = new LinkedList<Person>();demo1(personList) 看上去Person是Object的子類,可以透明地向上轉(zhuǎn)型,成功調(diào)用接口,其實不然。注意List<Object>和List<Person>是兩個平行的不同的參數(shù)類型,不存在任何的繼承掛關(guān)系。那么如果我確實想設(shè)計一個通用的接口怎么辦呢?可以設(shè)計成public void demo2(List<?> list)這樣List<Teacher> List<Student>就都可以使用了。但是仔細想一想,這樣的接口和public void demo3(List list)有什么區(qū)別嗎?毫無區(qū)別。應(yīng)為demo2這個接口中如果想對list中的元素進行處理,拿到手里的還是Object,免不了向下轉(zhuǎn)型。對于Java語言來說"泛"不是問題,Object那是相當?shù)姆海敕盒偷哪康闹痪褪抢?/span>T來對類型進行收斂,簡化語法的同時減少出錯的肯能性.但現(xiàn)在又出現(xiàn)了向下轉(zhuǎn)型,那?有什么意義嗎?當然是有意義的.不過要引入一個新的語法.Public void demo4(List<? extends Person>),這樣既保證List<Student>,List<Teacher>可以使用這個接口,又保證了接口中可以以Person這個基類進行統(tǒng)一操作.以上就是泛型使用的時候需要主義的問題.
下面說說泛型在框架設(shè)計時候的用處. 首先我有一個EntityBean(請不要和EJB2.1那個UGLY的EntityBean作任何聯(lián)想)作為POJO的統(tǒng)一基類,里面完成了一些toXML,toString,equals,hashCode,copyProperties,clone,getId等統(tǒng)一方法.我利用Dozer來在寫clone方法時,發(fā)現(xiàn)返回Object類型.那么子類在使用的時候就不許強制轉(zhuǎn)型,客戶端使用不是很爽. 用了泛型就能很容易解決問題 public class Entity<T> { public T clone() { return this.clone(); } }
public class NewsBean extends Entity<NewsBean>{ public static void main(String args[]) { NewsBean nb1 = new NewsBean(); NewsBean nb2 = nb1.clone(); } }
當然不用泛型也能解決這個問題,就是在 NewsBean類里面寫public NewsBean clone()方法,然后在里面調(diào)用基類的clone方法.這是采用窄化返回類型的方法來對基類的返回類型進行收斂.
下面說說取得類型T的class的方法,用BaseHibernateDao來做例子 import java.lang.reflect.ParameterizedType;
public class BaseHibernateEntityDao<T> { private Class<T> entityClass;
public BaseHibernateEntityDao() { entityClass = (Class<T>) ((ParameterizedType) getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; }
public Class<T> getEntityClass() { return entityClass; }
public T getEntity() throws InstantiationException, IllegalAccessException { return (T) entityClass.newInstance(); } }
class PersonDao extends BaseHibernateEntityDao<Person> { public static void main(String args[]) { PersonDao personDao = new PersonDao(); System.out.println(personDao.getEntityClass()); } } 最后打印的結(jié)果是class Person
子類什么都沒有干,沒有做任何的覆寫,只是在定義的時候為所繼承的父類確定了類型.著重看藍色的那句話.這就是取得T 的class的方法.最后之所以用[0]是因為基類只有一個類型T,如果有<T,E>那么這個Type數(shù)組也就會有兩個元素了.
最后請記住一點,雖然一般來說List<T> 和List都是可行的,也就是說泛型是透明的,如果你不指定T就默認類中用T定義的屬性都是Object類型的.但是在這個例子中,必須為BaseHibernateEntityDao指定類型,否則就會出錯,通不過ParameterizedType轉(zhuǎn)型這一步. |
|
|