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