Type是java.lang.reflect包下的一个接口,该接口代表所有类型的公共接口,Class是Type接口的实现类。
java采用泛型擦除的机制来引入泛型,也就是说,泛型仅仅是给编译器javac看的,来确保数据的安全性和免去数据类型转换,但是,一旦编译完成,所有和泛型相关的东西都被擦除,这一点也可以从类编译的class文件反编译看到。
在实际应用中,为了获得和泛型有关的信息,Java就新增了几种类型来代表不能被归一到Class类中的类型,但又和基本数据类型齐名的类型,通常使用的是如下两个:
GenericArrayType: 表示一种元素类型是参数化的类型或者类型变量的数组类型。
ParameterizedType: 表示一种参数化的类型。
为什么要引入这两种呢,实际上,在通过反射获取父类或者接口或者成员变量类型等方法中,如果涉及的是泛型的话,就无法获取不到了,所以才引入了上面两种类型。
举例说明整个过程:
Teacher和Student是实体,包含了id,name,age。对实体的操作主要为查询。通过泛型来抽取代码。
import com.jichu.Util.jdbcUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;
public class BaseDao<T> {
private Class targetClass;
private String tableName;
public BaseDao(){
Class clazz=this.getClass();
Type type=clazz.getGenericSuperclass();
ParameterizedType param=(ParameterizedType) type;
Type[]types=param.getActualTypeArguments();
Type target=types[0];
targetClass=(Class) target;
tableName=targetClass.getSimpleName().toLowerCase();
}
public List<T> findAll(){
QueryRunner qr=new QueryRunner(jdbcUtil.getDs());
try {
return (List<T>) qr.query("select *from "+tableName,new BeanListHandler<>(targetClass));
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public T findById(int id) {
QueryRunner qr=new QueryRunner(jdbcUtil.getDs());
try {
return (T)qr.query("select *from "+tableName+" where id=?",new BeanHandler<>(targetClass),new Object[]{id});
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
测试代码:
package com.jichu.generic;
import org.junit.Test;
import java.util.List;
public class TestDao {
@Test
public void testStu(){
StudentDao sdao=new StudentDao();
System.out.println(sdao.findById(1));
List<Student>list=sdao.findAll();
for (Student s:list ) {
System.out.println(s);
}
}
@Test
public void testTea(){
TeacherDao tdao=new TeacherDao();
// System.out.println(tdao.findById(2));
List<Teacher>list=tdao.findAll();
for (Teacher t:list ) {
System.out.println(t);
}
}
}
核心代码如下:
public BaseDao(){
1.Class clazz=this.getClass();
2.Type type=clazz.getGenericSuperclass();
3.ParameterizedType param=(ParameterizedType) type;
Type[]types=param.getActualTypeArguments();
4.Type target=types[0];
5.targetClass=(Class) target;
6.tableName=targetClass.getSimpleName().toLowerCase();
}
第一步获取类对象,class com.jichu.generic.StudentDao
第二步获取当前类对象的父类类型:com.jichu.generic.BaseDao<com.jichu.generic.Student>
第三步把父类类型转换为参数化对象:com.jichu.generic.BaseDao<com.jichu.generic.Student>第四步获取参数化对象的泛型列表:class com.jichu.generic.Student
第五步把type类型转为class类型
第六步获得最终参数:student