Java Type 说明

定义

Type是java编程语言所有类型的父接口。子类型包括:原始类型Class,参数化类型ParameterizedType,数组类型GenericArrayType,类型变量TypeVariable和基本类型Class

Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”,它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象;

public interface Type {
    /**
     * Returns a string describing this type, including information
     * about any type parameters.
     *
     * @implSpec The default implementation calls {@code toString}.
     *
     * @return a string describing this type
     * @since 1.8
     */
    default String getTypeName() {
        return toString();
    }
}
复制代码

⚠Class也是Type的一种,数组(不是数组类型)、枚举等“类型”是相对Class来说的

Type接口的意义

Type接口说从JDK5开始引入的,主要是为了泛型,没有泛型之前,只有原始类型(Class),即所有的原始类型都是通过Class类进行抽象。Class类的一个具体对象就代表一个指定的类型。泛型出现,也扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、泛型数组类型、这些都是Type的子接口。

为了程序的扩展性,Java引入了Type接口作为Class、ParameterizedType、TypeVariable、GenericArrayTypehe、WildcardType这几种类型的父接口。实现了Type类型参数接受以上五种子类的实参或者返回值类型就是Type类型的参数。

五种类型说明:

Class:对应原始类型和基本类型,原始类型指我们平常所指的 不带类型参数的类接口(非泛型类或者泛型类不带<>)注解枚举等结构

ParamterizedType:参数化类型,带有类型参数的类型,即常说的泛型,如:List<String>List<?>Class<T>Map<Integer,String> 等等

TypeVariable:类型变量,对应参数化类型<>里面的T,E等等,表示泛指任何类

GenericArrayType:(泛型)数组类型,指数组元素是参数化类型或者类型变量类型的数组类型。例如:T[]List<T>[]List<String>[]等等

WildcardType:通配符表达式或泛型表达式,比如[?][? extends T][? super T]。虽然WildcardType是Type的一个子接口,但并不是Java类型的一种

1、Class 原始或者基本类型

不带类型参数的类接口(非泛型类或者泛型类不带<>)注解枚举 等结构

测试代码

TypePrintUtil类代码见附录

public static void main(String[] args) throws NoSuchMethodException {
        testRawType();
    }

    private static void testRawType() throws NoSuchMethodException {
        Method rawType = JavaTypeTest.class.getDeclaredMethod("rawType", Object.class, int.class, String.class, int[].class,Enum.class);
        TypePrintUtil.printTypeName(rawType);
    }

    public int rawType(Object p1, int p2, String p3, int[] p4,Enum p5) {
        return 0;
    }
复制代码

打印结果

开始打印参数类型_____________________________ :
 开始打印当前方法第0个参数___________________ :
原始类型或者基本类型【class java.lang.Object】	类型接口【Object】
 开始打印当前方法第1个参数___________________ :
原始类型或者基本类型【int】	类型接口【int】
 开始打印当前方法第2个参数___________________ :
原始类型或者基本类型【class java.lang.String】	类型接口【String】
 开始打印当前方法第3个参数___________________ :
原始类型或者基本类型【class [I】	类型接口【int[]】
 开始打印当前方法第4个参数___________________ :
原始类型或者基本类型【class java.lang.Enum】	类型接口【Enum】

开始打印返回值类型____________________________ :
原始类型或者基本类型【int】	类型接口【int复制代码

2、ParameterizedType 参数化类型

List<String>List<?>Class<T>Map<Integer,String> 等泛型类或者泛型接口

类型说明

方法:

  • Type[] getActualTypeArguments() 返回一个 Type 对象数组,表示该类型的实际类型参数。(就是返回参数类型<>里的类型参数的类型,因为可能存在多个类型参数,例如Map<K,V>,所以返回的是一个Type数组)无论<>中嵌套几层<>,此方法仅能获取最外层<>中类型参数的类型。

  • Type getOwnerType() 返回Type对象,表示此类型是其成员之一的类型。如果此类型为顶层类型,则返回null

  • Type getRawType() 返回Type对象,表示声明此类型的类或者接口。例如List<T>返回就是List的类型即Class,简单来说就是返回<>前面的类型。

测试代码

public static void main(String[] args) throws NoSuchMethodException {
        testParameterizedType();
    }

    private static void testParameterizedType() throws NoSuchMethodException {
        Method rawType = JavaTypeTest.class.getDeclaredMethod("parameterizedType", List.class, List.class, Test.class);
        TypePrintUtil.printTypeName(rawType);
    }

    public <T> Map<String, T> parameterizedType(List<String> p1, List p2, Test<String> p3) {
        return null;
    }

    public interface Test<T> {
    }
复制代码

打印结果

开始打印参数类型_____________________________ :
开始打印当前方法第0个参数___________________ :
ParameterizedType类型【java.util.List<java.lang.String>】	类型接口【ParameterizedType】
ParameterizedType类型,开始打印<>内ActualType类型_____________
      开始打印当前方法第0个参数___________________ :
      原始类型或者基本类型【class java.lang.String】	类型接口【String】
开始打印当前方法第1个参数___________________ :
原始类型或者基本类型【interface java.util.List】	类型接口【List】
开始打印当前方法第2个参数___________________ParameterizedType类型【com.mumu.type.JavaTypeTest.com.mumu.type.JavaTypeTest$Test<java.lang.String>】	类型接口【ParameterizedTypeParameterizedType类型,开始打印<>内ActualType类型_____________
      开始打印当前方法第0个参数___________________ :
      原始类型或者基本类型【class java.lang.String】	类型接口【String】

开始打印返回值类型____________________________ParameterizedType类型【java.util.Map<java.lang.String, T>】	类型接口【ParameterizedTypeParameterizedType类型,开始打印<>内ActualType类型_____________
      开始打印当前方法第0个参数___________________ :
      原始类型或者基本类型【class java.lang.String】	类型接口【String】
      开始打印当前方法第1个参数___________________TypeVariable类型【T】	类型接口【TypeVariableTypeVariable类型【TgenericDeclaration:【public java.util.Map com.mumu.type.JavaTypeTest.parameterizedType(java.util.List,java.util.List,com.mumu.type.JavaTypeTest$Test)】	bounds:【[class java.lang.Object]】
复制代码

3、TypeVarialbe 类型变量

类型变量,对应参数化类型<>里面的T,E等等,表示泛指任何类

类型说明

方法:

  • Type[] getBounds() 返回表示此类型变量上边界的 Type 对象的数组。注意,如果未显式声明上边界,则上边界为 Object。

  • D getGenericDeclaration() 返回 GenericDeclaration 对象,该对象表示声明此类型变量的一般声明。

  • String getName() 返回此类型变量的名称(T,E等等),它出现在源代码中。

测试代码+打印结果

参考ParameterizedType 参数化类型的测试代码和打印结果,返回值Map<String,T>中的T的类型即为类型变量类型

4、GenericArray (泛型)数组类型

(泛型)数组类型,指数组元素是【参数化类型或者类型变量类型】的数组类型。例如:T[]List<T>[]List<String>[]等等

类型说明

方法:

  • Type getGenericComponentType() 返回表示此数组的组件类型的 Type 对象。此方法创建数组的组件类型。获取泛型数组中元素的类型,要注意的是:无论从左向右有几个[]并列,这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值。

测试代码

public static void main(String[] args) throws NoSuchMethodException {
        testGenericArrayType();
    }

    private static void testGenericArrayType() throws NoSuchMethodException {
        Method rawType = JavaTypeTest.class.getDeclaredMethod("genericArrayType", Object[].class, List[].class, List[].class);
        TypePrintUtil.printTypeName(rawType);
    }

    public <T> void genericArrayType(T[] p1, List<String>[] p2, List<T>[] p3) {

    }
复制代码

打印结果

开始打印参数类型_____________________________ :
开始打印当前方法第0个参数___________________ :
GenericArrayType类型【T】	类型接口【TypeVariable】
开始打印当前方法第1个参数___________________ :
GenericArrayType类型【java.util.List<java.lang.String>】	类型接口【ParameterizedType】
开始打印当前方法第2个参数___________________ :
GenericArrayType类型【java.util.List<T>】	类型接口【ParameterizedType】

开始打印返回值类型____________________________ :
原始类型或者基本类型【void】	类型接口【void复制代码

5、WildcardType 通配符(泛型)表达式

通配符表达式或泛型表达式,比如[?][? extends T][? super T]。虽然WildcardType是Type的一个子接口,但并不是Java类型的一种

类型说明

方法:

  • Type[] getLowerBounds() 返回表示此类型变量下边界的 Type 对象的数组。注意,如果不存在显式声明的下边界,则下边界为类型 null。在此情况下,将返回长度为零的数组。

  • Type[] getUpperBounds() 返回表示此类型变量上边界的 Type 对象的数组。注意,如果不存在显式声明的上边界,则上边界为 Object。

附录

打印类型帮助类代码

public class TypePrintUtil {

    public static void printTypeName(Method method) {
        //获取方法的参数类型,按照参数顺序返回一个Type数组,如果没有参照则返回一个长度为0的数组
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        System.out.println("开始打印参数类型_____________________________ :");
        printTypesName(genericParameterTypes, "");

        //获取方法返回值的类型
        System.out.println("\n开始打印返回值类型____________________________ :");
        Type genericReturnType = method.getGenericReturnType();
        printTypeName(genericReturnType, "");
    }

    private static void printTypesName(Type[] genericParameterTypes, String space) {
        for (int i = 0; i < genericParameterTypes.length; i++) {
            System.out.println(space + "开始打印当前方法第" + i + "个参数___________________ :");
            Type genericParameterType = genericParameterTypes[i];
            printTypeName(genericParameterType, space);
        }
    }

    private static void printTypeName(Type genericParameterType, String space) {
        //类型为原始类型或者基本类型,只指平常所指的类,例如非泛型类,枚举,数组元素类非泛型,注解
        if (genericParameterType instanceof Class<?>) {
            Class<?> clazz = (Class<?>) genericParameterType;
            System.out.println(space + "原始类型或者基本类型【" + clazz + "】\t类型接口【" + clazz.getSimpleName() + "】");
        }
        //类型为ParameterizedType:如:List<T>、Map<Integer, String>、List<? extends Number> ,自定义泛型类XXX<T>等等
        if (genericParameterType instanceof ParameterizedType) {
            //获取此类型的实际类型,即<>内的类型,此方法仅获取第一层的类型,如果是List<List<T>>这种还需要在获取一次,才能得到T
            ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
            //打印类型
            System.out.println(space + "ParameterizedType类型【" + parameterizedType + "】\t类型接口【" + parameterizedType.getClass().getInterfaces()[0].getSimpleName() + "】");
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            System.out.println(space + "ParameterizedType类型,开始打印<>内ActualType类型_____________");
            printTypesName(actualTypeArguments, "      ");
        }
        //类型为GenericArrayType: 比如List<T>[],T[]这种。注意,这不是我们说的一般数组,而是表示一种【元素类型是参数化类型或者类型变量的】数组类型
        else if (genericParameterType instanceof GenericArrayType) {
            GenericArrayType genericArrayType = (GenericArrayType) genericParameterType;
            //返回表示此数组的组件类型的 Type 对象
            Type genericComponentType = genericArrayType.getGenericComponentType();
            System.out.println(space + "GenericArrayType类型【" + genericComponentType + "】\t类型接口【" + genericComponentType.getClass().getInterfaces()[0].getSimpleName() + "】");
        }
        //类型为TypeVariable: 如参数类型中T,E等类型变量,泛指任何类型
        else if (genericParameterType instanceof TypeVariable) {
            TypeVariable typeVariable = (TypeVariable) genericParameterType;
            Type[] bounds = typeVariable.getBounds();
            GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
            System.out.println(space + "TypeVariable类型【" + typeVariable + "】\t类型接口【" + typeVariable.getClass().getInterfaces()[0].getSimpleName() + "】");
            System.out.println(space + "TypeVariable类型【" + typeVariable + "】\tgenericDeclaration:【" + genericDeclaration + "】\tbounds:【" + Arrays.toString(bounds) + "】");
        }
        //WildcardType 通配符表达式,例如:【?】【? super T】【? extends T】,虽然WildcardType是Type的一个子接口,但并不是Java类型中的一种
        else if (genericParameterType instanceof WildcardType) {
            WildcardType wildcardType = (WildcardType) genericParameterType;
            System.out.println(space + "WildcardType类型【" + wildcardType + "】\t类型接口【" + wildcardType.getClass().getInterfaces()[0].getSimpleName() + "】");
        }
    }

}
复制代码

参考文章

java Type 详解

Type 接口【重要】

java知识总结之Type

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享