JAVA获取类的泛型信息
一、前言
在我写 SpringBoot JPA
通用controller
的过程中,发现可以直接使用 Entitymanager
进行实体类的操作,EntityManager
需要实体信息,因为第一次不熟悉EntityManager
的操作,所以要获取当前类的泛型信息,然后传入EntityManager
完成通用的接口操作。
二、以Dao
为例
实体接口
1 |
|
实体
1 | /** |
Dao
接口
1 |
|
Dao
实现
1 |
|
1 | { |
其它解读
一、Type接口
Type是所有类型的父接口,他有4个子接口和一个实现类。
Class比较常见,它表示的是原始类型。Class类的对象表示JVM中的一个类或接口。每个Java类在JVM里都表现为一个Class对象,可以通过“类名.class”、“对象.getClass()”、“Class.forName(“类名”)
”等方式获取Class对象。数组也被映射为Class对象,所有元素类型相同且维数相同的数组都共享同一个Class对象。
ParameterizedType表示的是参数化类型,例如List
ParameterizedType接口中常用的方法有3个,分别是:
(1) Type getRawType()——返回参数化类型中的原始类型,例如List
(2) Type[] getActualTypeArguments()——获取参数化类型的类型变量或是实际类型列表,例如Map<Integer,String>
的实际泛型列表是Integer和String。需要注意的是,该列表的元素类型是Type,也就是说,可能存在多重嵌套的情况。
(3) Type getOwerType()——返回的是类型所属的类型,例如存在A
接口与Map.Entry<K,V>接口,Map<K,V>是Map.Entry<K,V>接口的所有者。
TypeVariable表示的是类型变量,它用来反映的是JVM编译该泛型前的信息,例如List
该接口常用的方法有3个,分别是:
(1) Type[] getBounds()——获取类型变量的上边界,如果未明确声明上边界则默认为Object。例如Class
(2) D getGenericDeclaration()——获取声明该类型变量的原始类型,例如Test
(3) String getName()——获取在源码中定义的名字,上例中为K。
GenericArrayType表示的是数组类型且组成元素时ParameterizedType或TypeVariable,例如List
一个方法,它返回数组的组成元素类型。
WildcardType表示的通配符类型,例如? extends Number 和 ? super Integer。
Wildcard接口有两个方法,分别是:
(1) Type[] getUpperBounds()——返回类型变量的上边界。
(2) Type[] getLowerBounds()——返回类型变量的下边界。
二、ParameterizedType与TypeVariable的使用
1.未指定泛型参数的泛型类(例如:ArrayList
public class TypeTest {
public static void main(String[] args) {
System.out.println(“接口是否是泛型类:”+ (ArrayList.class.getGenericInterfaces()[0] instanceof ParameterizedType));
System.out.println(“泛型类的名称:”+ ArrayList.class.getGenericInterfaces()[0].getTypeName());
System.out.println(“泛型类的实现:”+ ArrayList.class.getGenericInterfaces()[0].getClass());
System.out.println(“是否是泛型参数:”+(((ParameterizedType)ArrayList.class.getGenericInterfaces()[0])
.getActualTypeArguments()[0] instanceof TypeVariable));
System.out.println(“泛型参数名称:”+((ParameterizedType)ArrayList.class.getGenericInterfaces()[0]).getActualTypeArguments()[0]
.getTypeName());
System.out.println(“泛型参数的实现:”+((ParameterizedType)ArrayList.class.getGenericInterfaces()[0]).getActualTypeArguments()[0]
.getClass());
}
}
//输出结果:
接口是否是泛型类:true
泛型类的名称:java.util.List
泛型类的实现:class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
是否是泛型参数:true
泛型参数名称:E
泛型参数的实现:class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在这里,我们使用的是ArrayList.class,如果使用new ArrayList
对象是被所有的不同具体类型的ArrayList实例 共享的(例如:new ArrayList
2.指定泛型参数的泛型类(例如:GenericSubClass
public class GenericClass
}
public class GenericSubClass1
}
public class GenericSubClass2 extends GenericClass
}
public class TypeTest {
public static void main(String[] args) {
Class clazz = GenericSubClass1.class;
//Class clazz = GenericSubClass2 .class;
//Class clazz = new GenericSubClass1().getClass();
//Class clazz = new GenericSubClass2().getClass();
System.out.println(“父类是否是泛型类:”+ (clazz.getGenericSuperclass() instanceof ParameterizedType));
System.out.println(“泛型类的名称:”+ clazz.getGenericSuperclass().getTypeName());
System.out.println(“泛型类的实现:”+ clazz.getGenericSuperclass().getClass());
System.out.println(“是否是泛型参数:”+(((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0] instanceof
TypeVariable));
System.out.println(“泛型参数名称:”+((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0]
.getTypeName());
System.out.println(“泛型参数的实现:”+((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0].getClass());
}
}
//输出结果:
父类是否是泛型类:true
泛型类的名称:com.arch.test.reflect.GenericClass
泛型类的实现:class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
是否是泛型参数:true
泛型参数名称:String
泛型参数的实现:class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
不管是使用”类.class”,还是使用”对象.getClass()”,得到的父类的泛型参数始终是String。