现在的位置: 首页 > 综合 > 正文

泛型

2014年09月05日 ⁄ 综合 ⁄ 共 2821字 ⁄ 字号 评论关闭

l泛型(Generic) 泛形的作用

lJDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。
l注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。
l泛形的基本术语,以ArrayList<E>为例:<>念着typeof
ArrayList<E>中的E称为类型参数变量
ArrayList<Integer>中的Integer称为实际类型参数
整个称为ArrayList<E>泛型类型
整个ArrayList<Integer>称为参数化的类型ParameterizedType 
l使用迭代器迭代泛形集合中的元素。
l使用增强for循环迭代泛形集合中的元素。
l存取HashMap中的元素。
l使用泛形时的几个常见问题:
使用泛形时,泛形类型须为引用类型,不能是基本数据类型
ArrayList<String> list = new ArrayList<Object>();错
ArrayList<Object> list = new ArrayList<String>(); 错
ArrayList<String> list = new ArrayList ();正确
ArrayList list = new ArrayList<String>();正确
l

l自定义泛形——泛型方法
lJava程序中的普通方法、构造方法和静态方法中都可以使用泛型。方法使用泛形前,必须对泛形进行声明,语法:<T> ,T可以是任意字母,但通常必须要大写。<T>通常需放在方法的返回值声明之前。例如:
public static <T> void doxx(T t);
public <T,E,K> T get(T t,E e,K k);//

l注意:
只有对象类型才能作为泛型方法的实际参数。
在泛型中可以同时有多个类型,例如:
public static <K,V> V getValue(K key) { return map.get(key);}
l自定义泛形——泛型类和反射泛形
l如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下:
public class GenericDao<T> {
private T field1;
public void save(T obj){}
public <E,K> T getId(int id,T t,E t,K k){}//T在定义在了类上所以不需在声明
public static <T,K> T comp(T t,K k){}//静态方法单独声明
}
l注意,静态方法不能使用类定义的泛形,而应单独定义泛形。

应用:
 //泛型类
public abstract class DaoSupport<T>{
	//得到类型参数变量T的实际类型
	protected Class<T> entityClass = getEntityClass();
	//实际传入的参数类型在数据库中对应表的名称,用于在hibernate的查询中构建hql语句
	protected String entityName= getEntityName(DaoSupport.this.entityClass);
	
	//getClass得到调用该方法的运行时类,即继承DaoSupport的相应子类
	public String getSubClass()
	{
		return getClass().getName();
	}
	 // 得到类型参数变量T的实际类型
	public Class<T> getEntityClass(){
		// 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
		Type parentType =getClass().getGenericSuperclass();
		//判断父类是否是泛型类
		if( parentType instanceof ParameterizedType)
		{
			ParameterizedType ptype = (ParameterizedType) parentType;
			//得到参数类型数组中第一个参数的真实的类型,即DaoSupport<T>中T的真实类型
			return (Class<T>)ptype.getActualTypeArguments()[0];
		}
		return null;
	}
	
	
	 /* 获取实体的名称
	 * @param <E>泛型方法声明,因为是静态方法所以泛型方法需要单独声明,
	 * @param clazz 实体类
	 * @return 实体类claz在数据库中对应表的名称
	 * */
	protected static <E> String getEntityName(Class<E> clazz){
		//简单类型名称
		String entityname = clazz.getSimpleName();
		//如果该类上面有Entity注解,且注解中有值,则取该值为该类在数据库中对应的表名称
		Entity entity = clazz.getAnnotation(Entity.class);
		if(entity.name()!=null && !"".equals(entity.name())){
			entityname = entity.name();
		}
		return entityname;
	}
}

DaoSupport的子类:

public class GoodServiceImpl extends DaoSupport<Good>{

}
Good类
@Entity(name="Product")
public class Good {
	private String id;
	private String name;
     get/set方法省略
}

测试代码:

@Test
	public void getGenericClass() {
		GoodServiceImpl service = new GoodServiceImpl();
		//得到调用该方法的运行时类
		System.out.println(service.getSubClass());
		//GoodServiceImpl父类DaoSupport<T>中类型参数T的实际传入类型
		Class clazz = service.getEntityClass();
		//GoodServiceImpl父类DaoSupport<T>中类型参数T的实际传入类型的名称
		System.out.println(clazz.getName());
		//实体类clazz在数据库中对应表的名称
		System.out.println(service.getEntityName(clazz));
	}

测试结果:

com.liang.service.impl.GoodServiceImpl
com.liang.bean.Good
Product

抱歉!评论已关闭.