例如: 假设此时有一个User类,那么要获取该User类的真实类型的话,可以直接使用类名+".class"获取: ”User.class“
或者,通过User类的实例 user.getClass() 来获取;
上面两个例子是已经确定该类的类型是User类型了,所以,才可以使用上面的方法。
而泛型类因为还不能确定是什么类型,所以没办法使用上面的两个方法(实例.getClass(),类名.class);
如果类是泛型的话,那么该如何获取呢?
我们可以通过获取该泛型类的子类的传入的类型参数来确定该泛型类的真实类型。
如:
有个类继承了一个泛型类,给该泛型类传入了一参数 "User" --->这个参数就是解决问题的关键点了
public UserDao extends BaseDaoImpl<User>{
.....
}
该泛型类BaseDaoImpl<T>的代码如下:
public BaseDaoImpl() {
Class c = this.getClass();
Type t = c.getGenericSuperclass();
if (t instanceof ParameterizedType) {
// System.out.println("in if");
Type[] p = ((ParameterizedType) t).getActualTypeArguments();
// System.out.println(Arrays.toString(p));
this.clazz = (Class<T>) p[0];
}
}
BaseDaoImpl<T>的构造函数中的 this 指的是子类的实例。
this.getClass()获取子类的真实类型;
c.getGenericSuperclass(); 获取泛型父类
t.getActualTypeArguments(); 通过该泛型父类来获取真实的类型参数的数组;也就是获取泛型父类的尖括号里面的参数<T>,
因为泛型的尖括号是可以有多个参数的,所以该方法返回的是一个数组。
p[0](既:t.getActualTypeArguments()[0]); 获取该数组的第一个值。因为我们知道在该例子中BaseDaoImpl<T>只有一个参数T。所以我们只需要获取第一个值就可以了。
在这里需要注意的是:范式应该在编译的时候就指定,而不是运行时。
如果我把上面BaseDaoImpl(){ }改成如下这样子:
[错误示范]
public BaseDaoImpl() {
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
//输出结果,验证类型名称是否正确
//System.out.println("clazz --> " + clazz.getSimpleName()); //getSimpleName()是返回不包含包名的类名称
}
上面这段代码,因为在编译器进行编译的时候,还不能确定泛型的具体类型,所以会报如下的错误:
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
====================================================================
结束。