【Spring源码分析】ResolvableType

news2024/11/18 12:32:48

【Spring源码分析】ResolvableType

参考
目录

文章目录

      • 【Spring源码分析】ResolvableType
          • 一、ParameterizedType 参数化类型,即泛型;例如:List< T>、Map< K,V>等带有参数化的对象;
          • 二、GenericArrayType—— 泛型数组 泛型数组,描述的是形如:A< T>[]或T[]类型变量和原始类型
          • 三、TypeVariable
          • 四、WildcardType
          • 五、获取父接口父类中的泛型参数,使用原生和spring ResolvableType

Type
在这里插入图片描述

所有类型的类型是常见的超接口Java编程语言。这些包括原始类型,参数化的类型,数组类型,类型变量和原始类型(These include raw types, parameterized types, array types, type variables and primitive types).它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象;

Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型(Class);

原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
参数化类型,就是我们平常所用到的泛型List、Map;
数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;
基本类型,也就是我们所说的java的基本类型,即int,float,double等

一、ParameterizedType 参数化类型,即泛型;例如:List< T>、Map< K,V>等带有参数化的对象;

作用于Class的Field上面

Type[] getActualTypeArguments(); 返回 这个 Type 类型的参数的实际类型数组。

package com.lvyuanj.standard.resolvabletypes;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * ParameterizedType 使用测试 参数化类型
 *
 */
@Slf4j
public class ParameterizedTypeTest {

    /**
     * 1、map: 获取ParameterizedType:class java.lang.String
     * 2、map: 获取ParameterizedType:class com.wangji.demo.ParameterizedTypeTest
     * 3、map:getOwnerType is null
     * 4、map:getRawType:interface java.util.Map
     */
    private Map<String, ParameterizedTypeTest> map;
    /**
     * 1、set1: 获取ParameterizedType:class java.lang.String
     * 2、set1:getOwnerType is null
     * 3、set1:getRawType:interface java.util.Set
     */
    private Set<String> set1;
    /**
     * 1、 clz: 获取ParameterizedType:?
     * 2、 clz:getOwnerType is null
     * 3、clz:getRawType:class java.lang.Class
     */
    private Class<?> clz;
    /**
     * 1、holder: 获取ParameterizedType:class java.lang.String
     * 2、holder:getOwnerType:class com.wangji.demo.ParameterizedTypeTest
     * 3、holder:getRawType:class com.wangji.demo.ParameterizedTypeTest$Holder
     */
    private Holder<String> holder;

    /**
     * 1、list: 获取ParameterizedType:class java.lang.String
     * 2、list:getOwnerType is null
     * 3、list:getRawType:interface java.util.List
     */
    private List<String> list;
    /**
     * str:is not ParameterizedType
     */
    private String str;
    /**
     * i:is not ParameterizedType
     */
    private Integer i;
    /**
     * set:is not ParameterizedType
     */
    private Set set;
    /**
     *  aList:is not ParameterizedType
     */
    private List aList;
    /**
     * 1、entry: 获取ParameterizedType:class java.lang.String
     * 2、entry: 获取ParameterizedType:class java.lang.String
     * 3、entry:getOwnerType:interface java.util.Map
     * 4、entry:getRawType:interface java.util.Map$Entry
     */
    private Map.Entry<String, String> entry;


    static class Holder<V> {

    }

    public static void testParameterizedType() {
        Field f = null;
        try {
            Field[] fields = ParameterizedTypeTest.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];
                if(f.getName().equals("log")){
                    continue;
                }
                System.out.println(f.getName()+" == " + f.getType());
                if(f.getGenericType() instanceof ParameterizedType){
                    ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
                    for(Type type :parameterizedType.getActualTypeArguments()){
                        log.info(f.getName()+": 获取ParameterizedType:"+type);
                    }
                    if(parameterizedType.getOwnerType() !=null){
                        log.info(f.getName()+":getOwnerType:"+parameterizedType.getOwnerType());
                    }else{
                        log.info(f.getName()+":getOwnerType is null");
                    }
                    if(parameterizedType.getRawType() !=null){
                        log.info(f.getName()+":getRawType:"+parameterizedType.getRawType());
                    }
                }else{
                    log.info(f.getName() + ":is not ParameterizedType ");
                }
            }
        }catch (Exception e){
            log.error("error",e);
        }
    }


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

运行结果如下:

map == interface java.util.Map
11:04:52.041 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - map: 获取ParameterizedType:class java.lang.String
11:04:52.047 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - map: 获取ParameterizedType:class com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest
11:04:52.047 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - map:getOwnerType is null
11:04:52.048 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - map:getRawType:interface java.util.Map
set1 == interface java.util.Set
11:04:52.049 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - set1: 获取ParameterizedType:class java.lang.String
11:04:52.049 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - set1:getOwnerType is null
11:04:52.049 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - set1:getRawType:interface java.util.Set
clz == class java.lang.Class
11:04:52.050 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - clz: 获取ParameterizedType:?
11:04:52.050 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - clz:getOwnerType is null
11:04:52.050 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - clz:getRawType:class java.lang.Class
holder == class com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest$Holder
11:04:52.051 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - holder: 获取ParameterizedType:class java.lang.String
11:04:52.051 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - holder:getOwnerType:class com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest
11:04:52.051 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - holder:getRawType:class com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest$Holder
list == interface java.util.List
11:04:52.051 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - list: 获取ParameterizedType:class java.lang.String
11:04:52.051 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - list:getOwnerType is null
11:04:52.052 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - list:getRawType:interface java.util.List
str == class java.lang.String
11:04:52.052 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - str:is not ParameterizedType 
i == class java.lang.Integer
11:04:52.052 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - i:is not ParameterizedType 
set == interface java.util.Set
11:04:52.052 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - set:is not ParameterizedType 
aList == interface java.util.List
11:04:52.052 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - aList:is not ParameterizedType 
entry == interface java.util.Map$Entry
11:04:52.053 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - entry: 获取ParameterizedType:class java.lang.String
11:04:52.053 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - entry: 获取ParameterizedType:class java.lang.String
11:04:52.053 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - entry:getOwnerType:interface java.util.Map
11:04:52.053 [main] INFO  com.lvyuanj.standard.resolvabletypes.ParameterizedTypeTest - entry:getRawType:interface java.util.Map$Entry
二、GenericArrayType—— 泛型数组 泛型数组,描述的是形如:A< T>[]或T[]类型变量和原始类型

作用于Class的method上面

package com.lvyuanj.standard.resolvabletypes;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.*;
import java.util.List;

/**
 * GenericArrayType—— 泛型数组
 * 泛型数组,描述的是形如:A<T>[]或T[]类型
 *   is either a parameterized type or a type variable.
 */
@Slf4j
public class GenericArrayTypeTest<T> {

    /**
     * 含有泛型数组的才是GenericArrayType
     * @param pTypeArray GenericArrayType type :java.util.List<java.lang.String>[];
     * genericComponentType:java.util.List<java.lang.String>
     * @param vTypeArray  GenericArrayType type :T[];genericComponentType:T
     * @param list ParameterizedType type :java.util.List<java.lang.String>;
     * @param strings type :class [Ljava.lang.String;
     * @param test type :class [Lcom.wangji.demo.GenericArrayTypeTest;
     */
    public void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray
    , List<String> list, String[] strings, GenericArrayTypeTest[] test) {
    }

    /**
     * 1、getGenericComponentType
     * 返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)
     * 、T[] 中的T(TypeVariableImpl);
     * 值得注意的是,无论是几维数组,getGenericComponentType()方法都只会脱去最右边的[],返回剩下的值;
     */
    public static void testGenericArrayType() {
        Method[] declaredMethods = GenericArrayTypeTest.class.getDeclaredMethods();
        for(Method method :declaredMethods){
            if(method.getName().startsWith("main")){
                continue;
            }
            log.info("declare Method:"+method);
            /**
             * 获取当前参数所有的类型信息
             */
            Type[] types = method.getGenericParameterTypes();
            for(Type type: types){
                if(type instanceof ParameterizedType){
                    log.info("ParameterizedType type :"+type);
                }else if(type instanceof GenericArrayType){
                    log.info("GenericArrayType type :"+type);
                    Type genericComponentType = ((GenericArrayType) type).getGenericComponentType();
                    /**
                     * 获取泛型数组中元素的类型,要注意的是:无论从左向右有几个[]并列,
                     * 这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值。
                     */
                    log.info("genericComponentType:"+genericComponentType);
                }else if(type instanceof WildcardType){
                    log.info("WildcardType type :"+type);
                }else if(type instanceof  TypeVariable){
                    log.info("TypeVariable type :"+type);
                }else {
                    log.info("type :"+type);
                }
            }
        }
    }

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

运行结果:

11:31:23.706 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - declare Method:public void com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest[])
11:31:23.718 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - GenericArrayType type :java.util.List<java.lang.String>[]
11:31:23.718 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - genericComponentType:java.util.List<java.lang.String>
11:31:23.718 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - GenericArrayType type :T[]
11:31:23.719 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - genericComponentType:T
11:31:23.719 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - ParameterizedType type :java.util.List<java.lang.String>
11:31:23.719 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - type :class [Ljava.lang.String;
11:31:23.719 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - type :class [Lcom.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest;
11:31:23.719 [main] INFO  com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest - declare Method:public static void com.lvyuanj.standard.resolvabletypes.GenericArrayTypeTest.testGenericArrayType()
三、TypeVariable

TypeVariable Interface TypeVariable< D extends GenericDeclaration>
在这里插入图片描述

泛型的类型变量,指的是List< T>、Map< K,V>中的T,K,V等值,实际的Java类型是TypeVariableImpl(TypeVariable的子类;此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接,例如 List< T extends Number & Serializable>;其中,& 后必须为接口;

1、Type[] getBounds() 类型对应的上限,默认为Object
2、D getGenericDeclaration() 获取声明该类型变量实体,也就是TypeVariableTest< T>中的TypeVariableTest
3、String getName() 获取类型变量在源码中定义的名称;

package com.lvyuanj.standard.resolvabletypes;

import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.lang.reflect.*;
import java.util.List;

/**
 * Interface TypeVariable<D extends GenericDeclaration> , 
 * D - the type of generic declaration that declared the underlying type variable.
 * 类型变量是类型变量的公共超接口。类型变量是第一次使用反射方法创建的,如在这个包中指定的。
 * 如果类型变量T由类型(即类、接口或注释类型)T引用,并且T由第n个封闭类T(参见JLS.1.2)来声明,
 * 那么T的创建需要T的第i个包围类的分辨率(参见JVMS 5),对于i=0到n,包含。创建类型变量不能导致其边界的创建。 
 * 重复创建类型变量没有任何效果。
 * <p>
 * 可以在运行时实例化多个对象以表示给定的类型变量。即使类型变量只创建一次, 
 * 但这并不意味着缓存表示类型变量的实例的任何要求。
 * 但是,表示一个类型变量的所有实例必须是相等的()。因此,类型变量的用户不能依赖实现该接口的类实例的标识。
 * <p>
 * 泛型的类型变量,指的是List<T>、Map<K,V>中的T,K,V等值,实际的Java类型是TypeVariableImpl 
 * (TypeVariable的子类); 
 * 此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;值得注意的是,类型变量的上限可以为多个, 
 * 必须使用&符号相连接,例如 List<T extends Number & Serializable>;其中,& 后必须为接口;
 * 没有指定的话 ,V 的 上边界 属于  Object
 */
@Slf4j
public class TypeVariableTest<T extends Number & Serializable, V> {
    /**
     * TypeVariable
     */
    private T key;

    /**
     * TypeVariable
     */
    private V value;

    /**
     * GenericArrayType V[]-> V TypeVariable 两种混合起来了
     */
    private V[] values;
    /**
     * 原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
     * 基本类型,也就是我们所说的java的基本类型,即int,float,double等
     */
    private String str;

    /**
     * 获取ParameterizedType List<T> -> T TypeVariable 两种混合起来了
     */
    private List<T> tList;

    /**
     * 从这个例子中可以看出来各种类型之间是相互在使用的
     * TypeVariable<D extends GenericDeclaration>
     * GenericDeclaration  All Known Implementing Classes: Class, Constructor, Method

     */
    public static void testTypeVariableTest() {
        Field f = null;
        try {
            Field[] fields = TypeVariableTest.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];
                if (f.getName().equals("log")) {
                    continue;
                }
                log.info("begin ******当前field:" + f.getName() + " *************************");
                if (f.getGenericType() instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
                    for (Type type : parameterizedType.getActualTypeArguments()) {
                        log.info(f.getName() + ": 获取ParameterizedType:" + type);
                        if (type instanceof TypeVariable) {
                            printTypeVariable(f.getName(), (TypeVariable) type);
                        }
                    }
                    if (parameterizedType.getOwnerType() != null) {
                        log.info(f.getName() + ":getOwnerType:" + parameterizedType.getOwnerType());
                    } else {
                        log.info(f.getName() + ":getOwnerType is null");
                    }
                    if (parameterizedType.getRawType() != null) {
                        log.info(f.getName() + ":getRawType:" + parameterizedType.getRawType());
                    }
                } else if (f.getGenericType() instanceof GenericArrayType) {
                    GenericArrayType genericArrayType = (GenericArrayType) f.getGenericType();
                    log.info("GenericArrayType type :" + genericArrayType);
                    Type genericComponentType = genericArrayType.getGenericComponentType();
                    if (genericComponentType instanceof TypeVariable) {
                        TypeVariable typeVariable = (TypeVariable) genericComponentType;
                        printTypeVariable(f.getName(), typeVariable);
                    }
                } else if (f.getGenericType() instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) f.getGenericType();
                    printTypeVariable(f.getName(), typeVariable);
                } else {
                    log.info("type :" + f.getGenericType());
                }
                log.info("end ******当前field:" + f.getName() + " *************************");
            }
        } catch (Exception e) {
            log.error("error", e);
        }
    }

    /**
     * 1、Type[] getBounds() 类型对应的上限,默认为Object
     * 2、D getGenericDeclaration()  获取声明该类型变量实体,也就是TypeVariableTest<T>中的TypeVariableTest
     * 3、String getName() 获取类型变量在源码中定义的名称;
     *
     * @param fieldName
     * @param typeVariable
     */
    private static void printTypeVariable(String fieldName, TypeVariable typeVariable) {
        for (Type type : typeVariable.getBounds()) {
            log.info(fieldName + ": TypeVariable getBounds " + type);
        }
        log.info("定义Class getGenericDeclaration: " + typeVariable.getGenericDeclaration());
        log.info("getName: " + typeVariable.getName());
    }

    public static void main(String[] args) {
        testTypeVariableTest();
    }

}

运行结果

11:39:48.697 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - begin ******当前field:key *************************
11:39:48.708 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - key: TypeVariable getBounds class java.lang.Number
11:39:48.709 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - key: TypeVariable getBounds interface java.io.Serializable
11:39:48.711 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - 定义Class getGenericDeclaration: class com.lvyuanj.standard.resolvabletypes.TypeVariableTest
11:39:48.711 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - getName: T
11:39:48.711 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - end ******当前field:key *************************
11:39:48.711 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - begin ******当前field:value *************************
11:39:48.711 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - value: TypeVariable getBounds class java.lang.Object
11:39:48.711 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - 定义Class getGenericDeclaration: class com.lvyuanj.standard.resolvabletypes.TypeVariableTest
11:39:48.712 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - getName: V
11:39:48.712 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - end ******当前field:value *************************
11:39:48.712 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - begin ******当前field:values *************************
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - GenericArrayType type :V[]
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - values: TypeVariable getBounds class java.lang.Object
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - 定义Class getGenericDeclaration: class com.lvyuanj.standard.resolvabletypes.TypeVariableTest
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - getName: V
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - end ******当前field:values *************************
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - begin ******当前field:str *************************
11:39:48.713 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - type :class java.lang.String
11:39:48.714 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - end ******当前field:str *************************
11:39:48.716 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - begin ******当前field:tList *************************
11:39:48.717 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - tList: 获取ParameterizedType:T
11:39:48.717 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - tList: TypeVariable getBounds class java.lang.Number
11:39:48.717 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - tList: TypeVariable getBounds interface java.io.Serializable
11:39:48.717 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - 定义Class getGenericDeclaration: class com.lvyuanj.standard.resolvabletypes.TypeVariableTest
11:39:48.717 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - getName: T
11:39:48.718 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - tList:getOwnerType is null
11:39:48.718 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - tList:getRawType:interface java.util.List
11:39:48.718 [main] INFO  com.lvyuanj.standard.resolvabletypes.TypeVariableTest - end ******当前field:tList *************************
四、WildcardType

WildcardType represents a wildcard type expression, such as ?, ? extends Number, or ? super Integer.
通配符表达式,或泛型表达式,它虽然是Type的一个子接口,但并不是Java类型中的一种,表示的仅仅是类似 ? extends T、? super K这样的通配符表达式。 ?—通配符表达式,表示通配符泛型,但是WildcardType并不属于Java-Type中的一钟;例如:List< ? extends Number> 和 List< ? super Integer>;
1、Type[] getUpperBounds(); //获得泛型表达式上界(上限) 获取泛型变量的上边界(extends)
2、Type[] getLowerBounds(); //获得泛型表达式下界(下限) 获取泛型变量的下边界(super)

package com.lvyuanj.standard.resolvabletypes;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.*;
import java.util.List;

/**
 * WildcardType represents a wildcard type expression, such as ?, ? extends Number,  
 * or ? super Integer.
 * 通配符表达式,或泛型表达式,它虽然是Type的一个子接口,但并不是Java类型中的一种,表示的仅仅是类似 
 *  ? extends T、? super K这样的通配符表达式。
 * ?---通配符表达式,表示通配符泛型,但是WildcardType并不属于Java-Type中的一钟; 
 * 例如:List< ? extends Number> 和 List< ? super Integer>;
 * 1、Type[] getUpperBounds();  //获得泛型表达式上界(上限) 获取泛型变量的上边界(extends)
 * 2、Type[] getLowerBounds(); //获得泛型表达式下界(下限) 获取泛型变量的下边界(super)
 *
 */
@Slf4j
public class WildcardTypeTest {
    /**
     * 1、 a: 获取ParameterizedType:? extends java.lang.Number
     * 2、上界:class java.lang.Number
     */
    private List< ? extends Number> a;

    /**
     * b: 获取ParameterizedType:? super java.lang.String
     *  上届:class java.lang.Object
     *  下届:class java.lang.String
     */
    private List< ? super String> b;

    /**
     * c: 获取ParameterizedType:class java.lang.String
     */
    private List<String> c;

    /**
     * aClass: 获取ParameterizedType:?
     * 上届:class java.lang.Object
     */
    private Class<?> aClass;

    private String wangji;

    /**
     * 多种数据进行混合
     */
    public static void testWildcardType() {
        Field f = null;
        try {
            Field[] fields = WildcardTypeTest.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];
                if (f.getName().equals("log")) {
                    continue;
                }
                log.info("begin ******当前field:" + f.getName() + " *************************");
                if (f.getGenericType() instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
                    for (Type type : parameterizedType.getActualTypeArguments()) {
                        log.info(f.getName() + ": 获取ParameterizedType:" + type);
                        if (type instanceof WildcardType) {
                            printWildcardType((WildcardType) type);
                        }
                    }
                } else if (f.getGenericType() instanceof GenericArrayType) {
                    GenericArrayType genericArrayType = (GenericArrayType) f.getGenericType();
                    log.info("GenericArrayType type :" + genericArrayType);
                    Type genericComponentType = genericArrayType.getGenericComponentType();
                    if (genericComponentType instanceof WildcardType) {
                        printWildcardType((WildcardType) genericComponentType);
                    }
                } else if (f.getGenericType() instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) f.getGenericType();
                    log.info("typeVariable:" + typeVariable);

                } else {
                    log.info("type :" + f.getGenericType());
                    if (f.getGenericType() instanceof WildcardType) {
                        printWildcardType((WildcardType) f.getGenericType());
                    }
                }
                log.info("end ******当前field:" + f.getName() + " *************************");
            }
        } catch (Exception e) {
            log.error("error", e);
        }
    }

    private static void printWildcardType(WildcardType wildcardType) {
        for (Type type : wildcardType.getUpperBounds()) {
            log.info("上界:" + type);
        }
        for (Type type : wildcardType.getLowerBounds()) {
            log.info("下界:" + type);
        }
    }

    public static void main(String[] args) {
        testWildcardType();
    }
}

运行结果:

11:48:56.258 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - begin ******当前field:a *************************
11:48:56.287 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - a: 获取ParameterizedType:? extends java.lang.Number
11:48:56.287 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - 上界:class java.lang.Number
11:48:56.287 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - end ******当前field:a *************************
11:48:56.288 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - begin ******当前field:b *************************
11:48:56.288 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - b: 获取ParameterizedType:? super java.lang.String
11:48:56.288 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - 上界:class java.lang.Object
11:48:56.288 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - 下界:class java.lang.String
11:48:56.288 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - end ******当前field:b *************************
11:48:56.289 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - begin ******当前field:c *************************
11:48:56.289 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - c: 获取ParameterizedType:class java.lang.String
11:48:56.289 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - end ******当前field:c *************************
11:48:56.289 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - begin ******当前field:aClass *************************
11:48:56.290 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - aClass: 获取ParameterizedType:?
11:48:56.290 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - 上界:class java.lang.Object
11:48:56.291 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - end ******当前field:aClass *************************
11:48:56.291 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - begin ******当前field:wangji *************************
11:48:56.292 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - type :class java.lang.String
11:48:56.292 [main] INFO  com.lvyuanj.standard.resolvabletypes.WildcardTypeTest - end ******当前field:wangji *************************
五、获取父接口父类中的泛型参数,使用原生和spring ResolvableType
public class Parent<T> {
}


public interface IParent<T> {
}

使用原生和spring ResolvableType的比较

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1664229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SOCKET编程(4):SOCKET实战

SOCKET实战 Writen()、Readn()函数 send()函数存在需要发送的字符数len小于函数返回的已发送的字符数(ssize_t)的问题 recv()函数存在需要接收的字符数len小于函数返回的已接收的字符数(ssize_t)的问题 解决上述问题通过Writen()、Readn()函数实现 //buff是数据存储地址&a…

矩阵的压缩存储介绍

引入 概述 特殊矩阵的压缩 对称矩阵 三角矩阵 上三角矩阵&#xff1a;上三角区的元素不同&#xff0c;下三角区的元素相同。 存储不同元素的上三角区(计算前i-1行的所有元素之和(j-i1)[i行的列数]-1[下标由0开始],即以下标为0开始存储的下标)一个相同元素(下三角区) 下三角矩…

Verlog-串口发送-FPGA

Verlog-串口发送-FPGA 引言&#xff1a; ​ 随着电子技术的不断进步&#xff0c;串口通信已成为嵌入式系统和计算机外设中一种广泛使用的异步通信方式。串口通信因其简单性、可靠性以及对硬件资源的低要求&#xff0c;在数据传输领域扮演着重要角色。在FPGA&#xff08;现场可编…

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环 1、 for i in range(4):Dev.step(i6)for j in range(3):Dev.turnLeft()Dev.step(2)2、 for i in range(4):Dev.step(i3)for j in range(4):Dev.step(2)Dev.turnRight()Dev.step(-i-3)Dev.turnRight()3、 for i …

ICode国际青少年编程竞赛- Python-4级训练场-嵌套for循环练习

ICode国际青少年编程竞赛- Python-4级训练场-嵌套for循环练习 1、 for i in range(3):Spaceship.step(4)for j in range(4):Dev.step(2)Dev.turnRight()Spaceship.turnLeft()Spaceship.step(4)Spaceship.turnRight()2、 for i in range(4):Spaceship.step(6)for j in range(3):…

SpringBoot实现图片验证码

引入依赖 <dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version> </dependency>代码实现 package com.qiangesoft.captcha.controller;import com.wf.captcha.*…

【LeetCode刷题记录】简单篇-108-将有序数组转换为二叉搜索树

【题目描述】 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 【测试用例】 示例1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,…

面向对象进阶——内部类

1、初始内部类 什么是内部类&#xff1f; 类的五大成员&#xff1a; 属性、方法、构造方法、代码块、内部类 在一个类的里面&#xff0c;再定义一个类。 举例&#xff1a;在A类大的内部定义B类&#xff0c;B类就被称为内部类 public class Outer{ 外部类 public …

计数问题C++

题目&#xff1a; 思路&#xff1a; 1~n之间进行循环遍历&#xff0c;如果i不等于0继续循环&#xff0c;然后求出i的个位数与十位数&#xff0c;如果个位数为要查找的特定数字&#xff0c;计时器就1. 代码&#xff1a; #include<iostream> using namespace std; int n,x…

80.网络游戏逆向分析与漏洞攻防-移动系统分析-利用数据包尝试穿墙

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

蛋糕店做配送小程序的作用是什么

蛋糕烘焙除了生日需要&#xff0c;对喜吃之人来说往往复购率较高&#xff0c;除线下实体店经营外&#xff0c;更多的商家选择线上多种方式获客转化、持续提高生意营收&#xff0c;而除了进驻第三方平台外&#xff0c;构建品牌私域自营店铺也同样重要。 运用【雨科】平台搭建蛋…

【软考高项】四十二、八大绩效域知识点

一、干系人绩效域 预期目标 建立高效的工作关系 检查&#xff1a;干系人参与的连续性 干系人认同项目目标 检查&#xff1a; 变更频率 支持项目的干系人提高了满意度&#xff0c;从中受益 检查&#xff1a;干系人行为、干系人满意度、干系人相…

Linux基础之进程

目录 一、进程的基本概念 1.1 什么是进程 1.2 PCB的概念 1.3 进程的查看 1.3.1 查看进程方式一 1.3.2 查看进程的方式二 1.4 父进程与子进程 一、进程的基本概念 1.1 什么是进程 进程是什么&#xff1f; 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的…

基于StatefulSet控制器在Kubernetes上部署MySQL一主多从

一、前提--StatefuSet特性 1.1 有状态的节点控制器 -- StatefulSet 及其网络状态 容器的解决方案是针对无状态应用场景的最佳实践&#xff0c;但对于有状态应用来说&#xff0c;就并非如此了。Kubernetes 用 StatefulSet 解决了有状态应用编排的问题&#xff0c;本文我们就来…

设计模式-创建型-原型模式-prototype

工作经验类 public class WorkExperience implements Cloneable {private String workDate;private String company;public void setWorkDate(String workDate) {this.workDate workDate;}public void setCompany(String company) {this.company company;}Overridepublic Ob…

【35分钟掌握金融风控策略21】贷前额度策略

目录 贷前策略审批流程和统一额度管理 贷前策略审批流程 统一额度管理 预授信策略 贷前策略审批流程和统一额度管理 贷前包含了多个风控场景&#xff0c;这些风控场景的策略在执行时是否存在先后顺序呢&#xff1f;在贷前&#xff0c;除上述主要的风控场景&#xff0c;还有…

2024年4月12日饿了么春招实习试题【第三题】-题目+题解+在线评测,2024.4.12,饿了么机试【Kruskal 算法, 最小生成树】

2024年4月12日饿了么春招实习试题【第三题】-题目题解在线评测&#xff0c;2024.4.12&#xff0c;饿了么机试 &#x1f3e9;题目一描述&#xff1a;样例1样例2解题思路一&#xff1a;[Kruskal 算法](https://baike.baidu.com/item/%E5%85%8B%E9%B2%81%E6%96%AF%E5%8D%A1%E5%B0%…

【第19章】spring-mvc之全局异常处理

文章目录 前言一、全局异常处理1. 前端2. 后端 二、常见错误页1.增加界面2.web.xml3.异常处理4.效果 总结 前言 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习&#xff0c;本文就介绍了机器学习的基…

决策树的学习(Decision Tree)

1.对于决策树的概念&#xff1a; **本质上&#xff1a;**决策树就是模拟树的结构基于 if-else的多层判断 2.目的&#xff1a; 对实例进行分类的树形结构&#xff0c;通过多层判断&#xff0c;将所提供的数据归纳为一种分类规则。 3.优点&#xff1a; 1.计算量小&#xff0c;…

vs2019 STL库里 判断函数类型的模板 is_function_v 与 is_const_v

&#xff08;1&#xff09;源代码如下&#xff1a; 经简单代码测试后&#xff0c;得出 vs2019 的 c 编译器 和 其 STL 库的观点与设计&#xff1a;is_const_v 用来判断类型 T 内是否含有 const 修饰符&#xff0c;含有 const 则返回真。但若 T 是含有 const 的引用类型&#xf…