Java泛型的运用
说来惭愧,jdk1.6都快出来了,1.5的泛型还没怎么用过。顶多用用List<Person>搭配foreach语法来简化一些代码。前段时间发现在设计Base类的时候发现不用泛型就免不了Object的转型,相当不爽。前不久在江南白衣的blog上面看了获取T.class的方法,收益匪浅。
下面说几个泛型使用时注意的问题。
对于public void demo1(List<Object>list)这个接口,我可以这样使用吗?
List<Person> personList = new LinkedList<Person>();demo1(personList)
看上去Person是Object的子类,可以透明地向上转型,成功调用接口,其实不然。注意List<Object>和List<Person>是两个平行的不同的参数类型,不存在任何的继承挂关系。那么如果我确实想设计一个通用的接口怎么办呢?可以设计成public void demo2(List<?> list)这样List<Teacher> List<Student>就都可以使用了。但是仔细想一想,这样的接口和public void demo3(List list)有什么区别吗?毫无区别。应为demo2这个接口中如果想对list中的元素进行处理,拿到手里的还是Object,免不了向下转型。对于Java语言来说"泛"不是问题,Object那是相当的泛.引入泛型的目的之一就是利用T来对类型进行收敛,简化语法的同时减少出错的肯能性.但现在又出现了向下转型,那?有什么意义吗?当然是有意义的.不过要引入一个新的语法.Public void demo4(List<? extends Person>),这样既保证List<Student>,List<Teacher>可以使用这个接口,又保证了接口中可以以Person这个基类进行统一操作.以上就是泛型使用的时候需要主义的问题.
下面说说泛型在框架设计时候的用处.
首先我有一个EntityBean(请不要和EJB2.1那个UGLY的EntityBean作任何联想)作为POJO的统一基类,里面完成了一些toXML,toString,equals,hashCode,copyProperties,clone,getId等统一方法.我利用Dozer来在写clone方法时,发现返回Object类型.那么子类在使用的时候就不许强制转型,客户端使用不是很爽.
用了泛型就能很容易解决问题
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()方法,然后在里面调用基类的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());
}
}
最后打印的结果是class Person
子类什么都没有干,没有做任何的覆写,只是在定义的时候为所继承的父类确定了类型.着重看蓝色的那句话.这就是取得T 的class的方法.最后之所以用[0]是因为基类只有一个类型T,如果有<T,E>那么这个Type数组也就会有两个元素了.
最后请记住一点,虽然一般来说List<T> 和List都是可行的,也就是说泛型是透明的,如果你不指定T就默认类中用T定义的属性都是Object类型的.但是在这个例子中,必须为BaseHibernateEntityDao指定类型,否则就会出错,通不过ParameterizedType转型这一步.
联系客服