获取泛型内的类型

270 阅读4分钟

1、Type 接口简介

Type 是 Java 语言中所有类型的公共父接口,其从 JDK5 开始引入,引入的目的主要是为了支持泛型

Type 和 泛型、反射 息息相关,建议先了解这两个概念再了解 Type,不然下面的内容肯定看不明白。

没有泛型的之前,Java 只有所谓的原始类型(raw types)。此时,所有的原始类型都通过字节码类 Class 进行抽象。Class 类的一个具体对象(例如 String.class)就代表一个指定的原始类型。

泛型的出现扩充了数据类型的概念,从只有原始类型(raw types)扩充了参数化类型、类型变量类型、泛型数组类型和通配符类型。他们都是 Type 的子接口。

为什么他们没有统一到 Class 下,而是增加一个 Type 呢?个人认为,主要是因为这几个新增的类型和之前的 Class 有比较大的区别,Class 源码有近四千行,对外提供的方法有一百多个,而新增的这几个类型接口中声明的方法都不超过 5 个。


// Type is the common superinterface 公共父接口 for all types in the Java programming language.
// These include raw types, parameterized types, array types, type variables and primitive types.
// @since 1.5
public interface Type {
    // Returns a string describing this type, including information about any type parameters.
    default String getTypeName() {
        return toString();
    }
}
// Class 也是 Type 的一个实现类
class Class<T> implements Serializable, GenericDeclaration, Type, AnnotatedElement
  • 所有已知子接口:GenericArrayTypeParameterizedTypeTypeVariable<D>WildcardType
  • 所有已知实现类:Class

2、Java 中的所有类型

  • raw type:原始类型,对应 Class

    • 即我们通常说的引用类型,包括普通的类,例如 String.classList.class
    • 也包括数组(Array.class)、接口(Cloneable.class)、注解(Annotation.class)、枚举(Enum.class)等
  • primitive types:基本类型,对应 Class

    • 包括 Built-in 内置类型,例如 int.classchar.classvoid.class
    • 也包括 Wrappers 内置类型包装类型,例如 Integer.classBoolean.classVoid.class
  • parameterized types:参数化类型,对应 ParameterizedType

    • 带有类型参数的类型,即常说的泛型,例如 List<T>Map<Integer, String>List<? extends Number>
    • 实现类 sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
  • type variables:类型变量类型,对应 TypeVariable<D>

    • 即参数化类型 ParameterizedType 中的 E、K 等类型变量,表示泛指任何类
    • 实现类 sun.reflect.generics.reflectiveObjects.TypeVariableImpl
  • array types:泛型数组类型,对应 GenericArrayType

    • 元素类型是参数化类型或者类型变量的泛型数组类型,例如 T[]
    • 实现类 sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl

Type 接口的另一个子接口 WildcardType 代表通配符表达式类型,或泛型表达式类型,比如?? super T? extends T,他并不是 Java 类型中的一种。

2.1、 ParameterizedType

ParameterizedType是Type的子接口,表示一个有参数的类型,例如Collection,Map<K,V>等。但实现上 ParameterizedType并不直接表示Collection和Map<K,V>等,而是表示 Collection和Map<String,String>等这种具体的类型。是不是看着眼熟,其实这就是我们常说的泛型。而ParameterizedType代表的是一个泛型的实例,我们就称ParameterizedType为“泛型实例”吧。

当创建泛型P(如:Collection)时,将解析P实例化的泛型类型声明(如:Collection),并且递归地创建P的所有泛型参数(如:String)。

实现这个接口的“类”必须实现一个equals()方法,该方法将任何“泛型类型”(如:Collection)声明相同且“类型参数”(如:String)也相同的两个“类”等同起来。

2.1.1、Type[] getActualTypeArguments()

获取“泛型实例”中<>里面的“泛型变量”(也叫类型参数)的值,这个值是一个类型。因为可能有多个“泛型变量”(如:Map<K,V>),所以返回的是一个Type[]。

注意:无论<>中有几层<>嵌套,这个方法仅仅脱去最外层的<>,之后剩下的内容就作为这个方法的返回值,所以其返回值类型是不确定的。

煮个栗子:

  1. List a1;//返回ArrayList,Class类型
  2. List<ArrayList> a2;//返回ArrayList,ParameterizedType类型
  3. List a3;//返回T,TypeVariable类型
  4. List<? extends Number> a4; //返回? extends Number,WildcardType类型
  5. List<ArrayList[]> a5;//返回ArrayList[],GenericArrayType 类型

2.1.2、Type getRawType()

声明泛型的类或者接口,也就是泛型中<>前面的那个值,即Map<K ,V>的Map。

2.1.3、Type getOwnerType()

获得这个类型的所有者的类型。这主要是对嵌套定义的内部类而言的,例如于对java.util.Map.Entry<K,V>来说,调用getOwnerType方法返回的就是interface java.util.Map。

如果当前类不是内部类,而是一个顶层类,那么getOwnerType方法将返回null。

3、variables 类型变量

ME1724295172284.png

类上获取类型变量

if(actualType instanceof Class){
    typeParameters = ((Class) actualType).getTypeParameters();
}

参考:www.cnblogs.com/baiqiantao/… 参考:blog.csdn.net/liyantianmi…