项目概况

Java泛型体系知识学习

2026-01-294 min read后端技术
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>,所以是ParameterizedType
    • ParameterizedType#getActualTypeArguments 下标0就是泛型Boy
  • School<Boy>[] schools 是具体类型,有泛型<Boy>,但是是数组类型所以是GenericArrayType

1.2 GenericArrayType 泛型数组

GenericArrayTypeParameterizedType是比较类似的,唯一的区别是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 是具体类型,且有泛型,但是不是数组所以是ParameterizedType
  • School<Boy>[] schools 是具体类型,且有泛型,但是数组所以就是GenericArrayType
    • GenericArrayType#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 = TypeVariable
  • TypeVariableObj<A> as = ParameterizedType
    • ParameterizedType#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是 ParameterizedType
    • ParameterizedType#getActualTypeArguments[0] = WildcardType#getUpperBounds[0] = String
    • ParameterizedType#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 }