Type接口是所有类型的超级接口,它提供了以下子接口:
ParameterizedType:参数化类型
GenericArrayType:泛型数组类型
WildcardType:通配符类型
TypeVariable:类型变量
一、准备工作
1、引入依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
2、创建实体
在cn.horse.reflect.entity包下新建FieldTypeClass类
package cn.horse.reflect.entity;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class FieldTypeClass {
private List<String> parameterizedTypeField;
private Map.Entry<String, Object> parameterizedTypeWithOwnerField;
private List<String>[] genericArrayTypeField;
private List<? extends Collection<String>> wildcardTypeWithExtendsField;
private List<? super List<String>> wildcardTypeWithSuperField;
}
二、Type
Class类直接实现了Type接口,这里通过获取Class对象的方式获取一个Type对象。
@Test
public void testType() {
Type type = FieldTypeClass.class;
assertThat(type.getTypeName()).isEqualTo("cn.horse.reflect.entity.FieldTypeClass");
}
三、ParameterizrdType
@Test
public void testParameterizedType() throws NoSuchFieldException {
// 获取定义字段的泛型类型
Type genericType = FieldTypeClass.class.getDeclaredField("parameterizedTypeField").getGenericType();
assertThat(genericType).isInstanceOf(ParameterizedType.class);
// 类型转换
ParameterizedType parameterizedType = (ParameterizedType) genericType;
// 获取owner类型
assertThat(parameterizedType.getOwnerType()).isNull();
// 获取类型名称
assertThat(parameterizedType.getTypeName()).isEqualTo("java.util.List<java.lang.String>");
// 获取原始类型
assertThat(parameterizedType.getRawType()).isEqualTo(List.class);
// 获取参数类型
assertThat(parameterizedType.getActualTypeArguments()[0]).isEqualTo(String.class);
}
@Test
public void testParameterizedTypeWithOwner() throws NoSuchFieldException {
// 获取定义字段的泛型类型
Type genericType = FieldTypeClass.class.getDeclaredField("parameterizedTypeWithOwnerField").getGenericType();
assertThat(genericType).isInstanceOf(ParameterizedType.class);
// 类型转换
ParameterizedType parameterizedType = (ParameterizedType) genericType;
// 获取owner类型
assertThat(parameterizedType.getOwnerType()).isEqualTo(Map.class);
// 获取类型名称
assertThat(parameterizedType.getTypeName()).isEqualTo("java.util.Map$Entry<java.lang.String, java.lang.Object>");
// 获取原始类型
assertThat(parameterizedType.getRawType()).isEqualTo(Map.Entry.class);
// 获取参数类型
assertThat(parameterizedType.getActualTypeArguments()[0]).isEqualTo(String.class);
assertThat(parameterizedType.getActualTypeArguments()[1]).isEqualTo(Object.class);
}
代码中我们使用先获取到了Field对象,再使用getGenericType方法获取了定义字段的泛型类型,对泛型类型是否是ParameterizedType类型进行了判断,使用getActualTypeArguments方法获取到了参数类型。
四、GenericArrayType
@Test
public void testGenericArrayType() throws NoSuchFieldException {
// 获取定义字段的泛型类型
Type genericType = FieldTypeClass.class.getDeclaredField("genericArrayTypeField").getGenericType();
assertThat(genericType).isInstanceOf(GenericArrayType.class);
// 类型转换
GenericArrayType genericArrayType = (GenericArrayType) genericType;
// 获取类型名称
assertThat(genericArrayType.getTypeName()).isEqualTo("java.util.List<java.lang.String>[]");
// 获取数组元素泛型类型
Type genericComponentType = genericArrayType.getGenericComponentType();
// 获取数组元素类型名称
assertThat(genericComponentType.getTypeName()).isEqualTo("java.util.List<java.lang.String>");
}
代码中我们使用先获取到了Field对象,再使用getGenericType方法获取了定义字段的泛型类型,对泛型类型是否是GenericArrayType类型进行了判断,使用getGenericComponentType方法获取到了数组元素泛型类型。
五、WildcardType
@Test
public void testWildcardTypeWithExtends() throws NoSuchFieldException {
// 获取定义字段的泛型类型
Type genericType = FieldTypeClass.class.getDeclaredField("wildcardTypeWithExtendsField").getGenericType();
assertThat(genericType).isInstanceOf(ParameterizedType.class);
// 类型转换
ParameterizedType parameterizedType = (ParameterizedType) genericType;
// 获取owner类型
assertThat(parameterizedType.getOwnerType()).isNull();
// 获取类型名称
assertThat(parameterizedType.getTypeName()).isEqualTo("java.util.List<? extends java.util.Collection<java.lang.String>>");
// 获取原始类型
assertThat(parameterizedType.getRawType()).isEqualTo(List.class);
// 获取参数类型
Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
assertThat(actualTypeArgument).isInstanceOf(WildcardType.class);
// 类型转换
WildcardType wildcardType = (WildcardType) actualTypeArgument;
// 获取通配符类型名称
assertThat(wildcardType.getTypeName()).isEqualTo("? extends java.util.Collection<java.lang.String>");
// 获取通配符类型下界
assertThat(Arrays.stream(wildcardType.getLowerBounds()).map(Type::getTypeName).toArray()).isEqualTo(new String[0]);
// 获取通配符类型上界
assertThat(Arrays.stream(wildcardType.getUpperBounds()).map(Type::getTypeName).toArray()).isEqualTo(new String[] { "java.util.Collection<java.lang.String>" });
}
@Test
public void testWildcardTypeWithSuper() throws NoSuchFieldException {
// 获取定义字段的泛型类型
Type genericType = FieldTypeClass.class.getDeclaredField("wildcardTypeWithSuperField").getGenericType();
assertThat(genericType).isInstanceOf(ParameterizedType.class);
// 类型转换
ParameterizedType parameterizedType = (ParameterizedType) genericType;
// 获取owner类型
assertThat(parameterizedType.getOwnerType()).isNull();
// 获取类型名称
assertThat(parameterizedType.getTypeName()).isEqualTo("java.util.List<? super java.util.List<java.lang.String>>");
// 获取原始类型
assertThat(parameterizedType.getRawType()).isEqualTo(List.class);
// 获取参数类型
Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
assertThat(actualTypeArgument).isInstanceOf(WildcardType.class);
// 类型转换
WildcardType wildcardType = (WildcardType) actualTypeArgument;
// 获取通配符类型名称
assertThat(wildcardType.getTypeName()).isEqualTo("? super java.util.List<java.lang.String>");
// 获取通配符类型下界
assertThat(Arrays.stream(wildcardType.getLowerBounds()).map(Type::getTypeName).toArray()).isEqualTo(new String[] { "java.util.List<java.lang.String>" });
// 获取通配符类型上界
assertThat(Arrays.stream(wildcardType.getUpperBounds()).map(Type::getTypeName).toArray()).isEqualTo(new String[] { "java.lang.Object" });
}
代码中我们使用先获取到了Field对象,再使用getGenericType方法获取了定义字段的泛型类型,对泛型类型是否是ParameterizedType类型进行了判断,使用getActualTypeArguments方法获取到了参数类型,再对参数类型进行了通配符类型的判断,最终获取到了通配符类型的信息。