Java泛型体系知识学习
reflections

一、Java泛型体系
Type 是 Java 语言中所有类型的公共父接口,其从 JDK5 开始引入,引入的目的主要是为了支持泛型。 Java的泛型体系还是比较复杂的, 不过没关系,本篇文章会从实战的角度来,学习泛型。
1.1 ParameterizedType 参数化泛型
ParameterizedType 是, 参数化泛型只要记住凡是带泛型的是明确的类型,只要不是数组GenericArrayType那么一定是ParameterizedType。
如下:
- List<?> list 中的 list
- Map<String,String> map中的map
- Map<String,String> map中的map
1.1.1 API 说明
ParameterizedType 一共有3个方法如下。
java
1public interface ParameterizedType extends Type {
2 // 获取泛型信息,输一个数组。因为可能泛型有多个
3 Type[] getActualTypeArguments();
4// 原始数据类型
5 Type getRawType();
6//
7 Type getOwnerType();
8}- getRawType 获取原始数据类型
- getActualTypeArguments 获取泛型信息,因为泛型可以是多个,所以返回是数组
1.1.2 代码示例
java
1public class Test {
2 class Girl implements Person {}
3 class Boy implements Person {}
4 interface Person {}
5 class School<A extends Boy & Person> {}
6 School<Boy> boySchool;
7School<Boy>[] schools;
8@Test
9 public void test() {
10 // class java.lang.Class
11 System.out.println(ReflectionUtils.findField(Test.class, "boy").getGenericType().getClass());
12// class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
13 System.out.println(ReflectionUtils.findField(Test.class, "boySchool").getGenericType().getClass());
14// class sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
15 System.out.println(ReflectionUtils.findField(Test.class, "schools").getGenericType().getClass());
16}
17}boy是具体类型,且不是泛型,所以是Class类型School<Boy> boySchool是具体类型,但是有泛型<Boy>,所以是ParameterizedTypeParameterizedType#getActualTypeArguments下标0就是泛型Boy
School<Boy>[] schools是具体类型,有泛型<Boy>,但是是数组类型所以是GenericArrayType
1.2 GenericArrayType 泛型数组
GenericArrayType和ParameterizedType是比较类似的,唯一的区别是GenericArrayType一定是数组,如果不是数组就是ParameterizedType
1.2.1 API 说明
GenericArrayType 只提供了一个方法就是获取泛型的方法
java
1public interface GenericArrayType extends Type {
2 // 获取数组泛型
3 Type getGenericComponentType();
4}1.2.2 代码示例
java
1public class Test {
2 class Girl implements Person {}
3 class Boy implements Person {}
4 interface Person {}
5 class School<A extends Boy & Person> {}
6 School<Boy> boySchool;
7 School<Boy>[] schools;
8 @Test
9 public void test2(){
10 GenericArrayType schoolsArrayType = (GenericArrayType) ReflectionUtils.findField(Test.class, "schools").getGenericType();
11 Type genericComponentType = schoolsArrayType.getGenericComponentType();
12 // learn.common.print.Test$School<learn.common.print.Test$Boy>
13 System.out.println(genericComponentType.getTypeName());
14 // class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
15 System.out.println(genericComponentType.getClass());
16 }
17}School<Boy> boySchool是具体类型,且有泛型,但是不是数组所以是ParameterizedTypeSchool<Boy>[] schools是具体类型,且有泛型,但是是数组所以就是GenericArrayTypeGenericArrayType#getGenericComponentType=School<Boy>=ParameterizedType
1.3 TypeVariable 泛型变量
TypeVariable变量泛型是比较好判断的,只要是变量泛型。一定就是TypeVariable。
1.3.1 API 说明
java
1public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
2 // 获取泛型信息
3 Type[] getBounds();
4
5 D getGenericDeclaration();
6
7 String getName();
8
9 AnnotatedType[] getAnnotatedBounds();
10}1.3.2 代码示例
java
1 class TypeVariableObj<A extends Number> {
2 A a;
3 TypeVariableObj<A> as;
4 }
5 @Test
6 public void test3() {
7 Type a = ReflectionUtils.findField(TypeVariableObj.class, "a").getGenericType();
8 // class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
9 System.out.println(a.getClass());
10
11 Type as = ReflectionUtils.findField(TypeVariableObj.class, "as").getGenericType();
12 // class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
13 System.out.println(as.getClass());
14 Type[] actualTypeArguments = ((ParameterizedType) as).getActualTypeArguments();
15 // A 因为只有1个泛型,所以直接去下标0
16 TypeVariable actualTypeArgument = (TypeVariable) actualTypeArguments[0];
17 System.out.println(actualTypeArgument.getTypeName());
18 }A a = TypeVariableTypeVariableObj<A> as = ParameterizedTypeParameterizedType#getActualTypeArguments()[0] = <A>
1.4 WildcardType 泛型表达式
WildcardType也比较好判断只要是通配符,可以简单理解,直接带有 ? 的泛型限定那么就是 WildcardType
1.4.1 API 说明
WildcardType通配符, 如 ?, ? extends Number, ? super Integer
java
1public interface WildcardType extends Type {
2 // 泛型上限
3 Type[] getUpperBounds();
4 // 泛型下限
5 Type[] getLowerBounds();
6}Type[] getUpperBounds();//获得泛型表达式上界(上限) 获取泛型变量的上边界(extends)Type[] getLowerBounds();//获得泛型表达式下界(下限) 获取泛型变量的下边界(super)
1.4.2 代码示例
java
1public class WildcardTypeTest {
2 Map<? extends String, ? super Number> map;
3 @Test
4 public void wildcardTypeTest() {
5 Field map = ReflectionUtils.findField(WildcardTypeTest.class, "map");
6 Type[] actualTypeArguments = ((ParameterizedType) map.getGenericType()).getActualTypeArguments();
7 // ? extends java.lang.String
8 System.out.println(((WildcardType) actualTypeArguments[0]).getTypeName());
9 // class java.lang.String
10 System.out.println(((WildcardType) actualTypeArguments[0]).getUpperBounds()[0]);
11 }
12}Map<? extends String, ? super Number> map中 map是ParameterizedTypeParameterizedType#getActualTypeArguments[0]=WildcardType#getUpperBounds[0]=StringParameterizedType#getActualTypeArguments[1]=WildcardType#getLowerBounds[0]=Number
二、泛型获取
通过上面的学习,我们可以使用原始API来获取各种泛型的信息,而Spring中有一个比较好用的工具。屏蔽了底层的 具体实现。比较方便。
2.1 获取接口泛型
java
1 class A {}
2 class B {}
3 interface School<T, K> {}
4 interface X extends School<A, B> {}
5 @Test
6 public void test() {
7 // 获取实现的接口是泛型的信息
8 ResolvableType resolvableType = ResolvableType.forClass(X.class);
9 Class<?> resolve1 = resolvableType.getInterfaces()[0].getGeneric(0).resolve();
10 // class learn.common.print.ColorConsoleTest$A
11 System.out.println(resolve1);
12 Class<?> resolve2 = resolvableType.getInterfaces()[0].getGeneric(1).resolve();
13 // class learn.common.print.ColorConsoleTest$B
14 System.out.println(resolve2);
15 }2.2 获取父类泛型
java
1 class A {}
2 class B {}
3 class School<T, K> {}
4 class X extends School<A, B> {}
5 @Test
6 public void test() {
7 // 获取实现的接口是泛型的信息
8 ResolvableType resolvableType = ResolvableType.forClass(X.class);
9 Class<?> resolve1 = resolvableType.getSuperType().getGeneric(0).resolve();
10 // class learn.common.print.ColorConsoleTest$A
11 System.out.println(resolve1);
12 Class<?> resolve2 = resolvableType.getSuperType().getGeneric(1).resolve();
13 // class learn.common.print.ColorConsoleTest$B
14 System.out.println(resolve2);
15 }2.3 获取字段泛型
java
1 class A {}
2 class B {}
3 class School<T, K> {}
4 class X {
5 private School<A, B> school;
6 }
7
8 @Test
9 public void test() {
10 // Spring的提供工具类,用于字段的泛型信息,Person<String>
11 ResolvableType resolvableType = ResolvableType.forField(Objects.requireNonNull(ReflectionUtils.findField(X.class, "school")));
12 System.out.println(resolvableType);
13 Class<?> resolve1 = resolvableType.getGeneric(0).resolve();
14 // class learn.common.print.ColorConsoleTest$A
15 System.out.println(resolve1);
16 Class<?> resolve2 = resolvableType.getGeneric(1).resolve();
17 // class learn.common.print.ColorConsoleTest$B
18 System.out.println(resolve2);
19 }2.4 获取方法泛型
java
1 class A {}
2 class B {}
3 class School<T, K> {}
4 class X {
5 public School<A, B> getSchool() {
6 return null;
7 }
8 }
9
10 @Test
11 public void test() {
12 // Spring的提供工具类,用于字段的泛型信息,Person<String>
13 ResolvableType resolvableType = ResolvableType.forMethodReturnType(Objects.requireNonNull(ReflectionUtils.findMethod(X.class, "getSchool")));
14 System.out.println(resolvableType);
15 Class<?> resolve1 = resolvableType.getGeneric(0).resolve();
16 // class learn.common.print.ColorConsoleTest$A
17 System.out.println(resolve1);
18 Class<?> resolve2 = resolvableType.getGeneric(1).resolve();
19 // class learn.common.print.ColorConsoleTest$B
20 System.out.println(resolve2);
21 }