public interface Type
在JDK手册中是这样解释的
我们可以看看继承关系 , 它有好多的子接口
Type体系包括原始类型 , 基本类型,数组类型 , 参数化类型 , 类型变量
1.ParameterizedType
表示一个参数化类型,就比如List<T> , Map<k,v>等 , 它包含了三个方法 , 在JDK文档中官方解释是这样的
1.1 getActualTypeArguments()
用下面的代码进行测试
/**
* @author: Liu Yuehui
* @ClassName: ParameterizedTypeTest
* @date: 2022/4/15 10:16
* @description: 测试 ParameterizedType
**/
public class ParameterizedTypeTest<T1 , T2> {
private final List<T1> list = new ArrayList<>();
private final Map<T1 , T2> map = new HashMap<>();
private final List<Map<T1, T2>> listMap = new ArrayList<>();
public static void main(String[] args) {
ParameterizedTypeTest<String, Number> parameterizedTypeTest = new ParameterizedTypeTest<>();
Field[] declaredFields = ParameterizedTypeTest.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
parameterizedTypeTest.testGetActualTypeArguments(declaredField.getName());
}
}
public void testGetActualTypeArguments(String name){
try {
Field list = ParameterizedTypeTest.class.getDeclaredField(name);
// 获取属性的泛型类型
Type genericType = list.getGenericType();
// 获取实际的Type类型 , sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
System.out.println("获取实际的Type类型 : " + genericType.getClass().getName());
ParameterizedType listParamType = (ParameterizedType) genericType;
Type[] listActualTypeArguments = listParamType.getActualTypeArguments();
for (Type listActualTypeArgument : listActualTypeArguments) {
System.out.println("当前属性["+name+"]的类型为 : " + listActualTypeArgument);
}
System.out.println();
}catch (Exception e){
e.printStackTrace();
}
}
}
可以看到都正常的获取到了类型 , 但是listMap和其他获取的不同 , 这是因为复杂类型他只会解析一个<> , 就比如
解析完之后类型就是Map , 他不会再往里面一层解析 , 解析为T1 , T2
1.2getRawType
获取<>前得值
1.3getOwnerType
获取泛型得拥有者
以下是完整的测试代码
/**
* @author: Liu Yuehui
* @ClassName: ParameterizedTypeTest
* @date: 2022/4/15 10:16
* @description: 测试 ParameterizedType
**/
public class ParameterizedTypeTest<T1 , T2> {
private List<T1> list;
private Map<T1 , T2> map;
private List<Map<T1, T2>> listMap;
private Map.Entry<T1 , T2> mapEntry;
public static void main(String[] args) {
ParameterizedTypeTest<String, Number> parameterizedTypeTest = new ParameterizedTypeTest<>();
Field[] declaredFields = ParameterizedTypeTest.class.getDeclaredFields();
Type genericType = null;
for (Field declaredField : declaredFields) {
String name = declaredField.getName();
// 获取属性的泛型类型
genericType = declaredField.getGenericType();
ParameterizedType listParamType = (ParameterizedType) genericType;
// 测试getActualTypeArguments
parameterizedTypeTest.testGetActualTypeArguments(listParamType , name);
// 测试getRawType
parameterizedTypeTest.testGetRawType(listParamType , name);
// 测试getOwnerType
parameterizedTypeTest.testGetOwnerType(listParamType , name);
System.out.println();
}
// 获取实际的Type类型 , sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
System.out.println("获取实际的Type类型 : " + genericType.getClass().getName());
}
public void testGetActualTypeArguments(ParameterizedType listParamType , String name){
Type[] listActualTypeArguments = listParamType.getActualTypeArguments();
for (Type listActualTypeArgument : listActualTypeArguments) {
System.out.println("当前属性["+name+"]的泛型类型为 : " + listActualTypeArgument);
}
}
public void testGetRawType(ParameterizedType listParamType , String name){
Type rawType = listParamType.getRawType();
System.out.println("当前属性["+name+"]的类型为 : " + rawType);
}
public void testGetOwnerType(ParameterizedType listParamType , String name){
Type ownerType = listParamType.getOwnerType();
System.out.println("当前属性["+name+"]泛型的拥有者为 : " + ownerType);
}
}
测试结果
2.GenericArrayType
表示组件类型是参数化类型或类型变量的数组类型 ,比如T[]
在源码中我们可以看到 , 他只有一个方法
关于这个方法的解释 , 在JDK文档中是这样说的
接下来用代码体现一下
public class GenericArrayTypeTest<T> {
private T[] arr;
private List<String>[] listArray;
public static void main(String[] args) throws NoSuchFieldException {
for (Field declaredField : GenericArrayTypeTest.class.getDeclaredFields()) {
Type type = GenericArrayTypeTest.class.getDeclaredField(declaredField.getName()).getGenericType();
System.out.println(declaredField.getName() + "字段的类型为 : " +((GenericArrayType)type).getGenericComponentType());
}
}
}
测试结果为 :
3.TypeVariable
在JDK文档中的解释是这样的
我们可以这么理解: 类型变量的父接口 , 就是泛型里边的类T , E , 即泛型变量
源码:
测试代码:
public class TypeVariableTest<T> {
T type;
List<T> typeList;
public static void main(String[] args) {
// 获取类上声明的泛型变量 getTypeParameters
TypeVariable<Class<TypeVariable>> typeVariable = TypeVariable.class.getTypeParameters()[0];
// 获取泛型变量的上边界 java.lang.reflect.GenericDeclaration
System.out.println(Arrays.toString(typeVariable.getBounds()));
// 如果类上申明了泛型
TypeVariable<Class<TypeVariableTest>> classType = TypeVariableTest.class.getTypeParameters()[0];
Class<TypeVariableTest> clazzDeclaration = classType.getGenericDeclaration();
System.out.println(clazzDeclaration);
// 如果方法上申明了泛型
Method[] methods = TypeVariableTest.class.getMethods();
Method method = Arrays.stream(methods)
.filter(m -> m.getName().equals("test"))
.collect(Collectors.toList())
.get(0);
TypeVariable methodType = (TypeVariable) method.getGenericParameterTypes()[0];
GenericDeclaration methodDeclaration = methodType.getGenericDeclaration();
System.out.println(methodDeclaration);
}
public <T> void test(T t) {
}
}
4.WildcardType
表示一个通配符型表达,如 ? , ? extends Number ,或 ? super Integer
源码内部一共有两个方法
这两个方法第一个是用来得到下边界Type的数组 , 第二个就是得到上边界Type得数组
测试代码:
public class WildcardTypeTest {
// 指定上界 Number,下边界默认为 []
private List<? extends Number> a;
// 指定下界 String,上边界默认是 Object
private List<? super String> b;
// 上界和下界都不指定,上边界默认是 Object,下边界默认为 []
private Class<?> clazz;
// 没有通配符,不是 WildcardType
private List<String> c;
public static void main(String[] args) {
Field[] fields = WildcardTypeTest.class.getDeclaredFields();
for (Field field : fields) {
Type genericType = field.getGenericType();
String name = field.getName();
if (genericType instanceof ParameterizedType) {
//2. 再从范型里拿到通配符类型
ParameterizedType parameterizedType = (ParameterizedType) genericType;
genericType = parameterizedType.getActualTypeArguments()[0];
if (genericType instanceof WildcardType) {
System.out.println("-------------" + name + "--------------");
WildcardType wildcardType = (WildcardType) genericType;
Type[] lowerTypes = wildcardType.getLowerBounds();
if (lowerTypes != null) {
System.out.println("上边界:" + Arrays.toString(lowerTypes));
}
Type[] upTypes = wildcardType.getUpperBounds();
if (upTypes != null) {
System.out.println("下边界:" + Arrays.toString(upTypes));
}
}
}
}
}
}
6.GenericDeclaration
GenericDeclaration 该接口用来定义哪些对象上是可以声明范型变量,目前实现 该接口的类包括 Class、Method、Constructor,也就是说只能在这几种对象上进行范型变量的声明(定义)。
它只有一个方法 , 这个方法的作用就是用来逐个获取该 GenericDeclaration 的范型变量声明。
public class GenericDeclarationTest<T> {
T test;
// 类上声明
class test<T>{}
// 构造方法声明
public <E> GenericDeclarationTest(E e) {
}
// 方法声明
public <K> void test(){
}
}
JDK中文手册
参考:
JDK 泛型之 Type - binarylei - 博客园