你真的了解Java泛型参数?spring ResolvableType更好的处理泛型

你真的了解Java泛型参数?spring ResolvableType更好的处理泛型

哈哈!你真的了解?我感觉了解了,但是真正的深入才知道自己了解甚少!spring 对于处理泛型参数使用啦ResolvableType,方便又快捷的帮助我们处理啦!很多类型的抽象,提供了统一的调用方式,更多的使用参考spring源码ResolvableTypeTest 不过我们自己对于Java的类型体系还是需要自己深入的了解的如下:

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);

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

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

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

/**
 * ParameterizedType 使用测试 参数化类型
 *
 * @author: wangji
 * @date: 2018/06/25 16:19
 */
@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;
                }
                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();
    }


}

GenericArrayType—— 泛型数组 泛型数组,描述的是形如:A< T>[]或T[]类型变量和原始类型

/**
 * GenericArrayType—— 泛型数组
 * 泛型数组,描述的是形如:A<T>[]或T[]类型
is either a parameterized type or a type variable.
 * @author: wangji
 * @date: 2018/06/25 17:26
 */
@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();
    }
}

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() 获取类型变量在源码中定义的名称;


/**
 * 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>;其中,& 后必须为接口;
 * @author: wangji
 * @date: 2018/06/25 19:03
 * 没有指定的话 ,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();
    }

}

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)


/**
 * 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)
 *
 * @author: wangji
 * @date: 2018/06/25 19:47
 */
@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();
    }
}

获取父接口父类中的泛型参数,使用原生和spring ResolvableType

/**
 * 测试继承获取泛型
 *
 * @author: wangji
 * @date: 2018/06/25 20:34
 */
public class Parent<T> {
}


/**
 * 测试泛型
 *
 * @author: wangji
 * @date: 2018/06/25 20:42
 */
public interface IParent<T> {
}

使用原生和spring ResolvableType的比较

/**
 * 测试泛型(理解了之前的那几个数据信息,是不是非常好理解处理啦)
 *
 * @author: wangji
 * @date: 2018/06/25 20:34
 */
@Slf4j
public class Children extends Parent<String> implements IParent<Long> {

    public static void main(String[] args) {
        /**
         * 这里是获取父类中泛型,如果有多个也是一样的方式哈哈!获取到的泛型参数还可能是 通配符表达式, 
         * 这里也是可以处理的,多个判断而已
         */
        Type genericSuperclassType = Children.class.getGenericSuperclass();
        if (genericSuperclassType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericSuperclassType) 
            .getActualTypeArguments();
            for (Type argumentType : actualTypeArguments) {
                log.info("父类ParameterizedType.getActualTypeArguments:" + argumentType);
            }
        }
        /**
         * 这里获取父接口中的泛型参数
         */
        Type[] genericInterfacesTypes = Children.class.getGenericInterfaces();
        for (Type interfaceType : genericInterfacesTypes) {
            if (interfaceType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) interfaceType) 
                .getActualTypeArguments();
                for (Type argumentType : actualTypeArguments) {
                    log.info("父接口ParameterizedType.getActualTypeArguments:" + argumentType);
                }
            }
        }
        /**
         言归正传,下面讲解ResolvableType。ResolvableType为所有的java类型提供了统一的数据结构以及API 
         ,换句话说,一个ResolvableType对象就对应着一种java类型。 
         我们可以通过ResolvableType对象获取类型携带的信息 
         (举例如下):
         1.getSuperType():获取直接父类型
         2.getInterfaces():获取接口类型
         3.getGeneric(int...):获取类型携带的泛型类型
         4.resolve():Type对象到Class对象的转换

         另外,ResolvableType的构造方法全部为私有的,我们不能直接new,只能使用其提供的静态方法进行类型获取:
         1.forField(Field):获取指定字段的类型
         2.forMethodParameter(Method, int):获取指定方法的指定形参的类型
         3.forMethodReturnType(Method):获取指定方法的返回值的类型
         4.forClass(Class):直接封装指定的类型
         */
        ResolvableType superResolvableType = ResolvableType.forClass(Children.class).getSuperType();
        log.info("supper:"+superResolvableType.resolveGenerics()[0]);

        ResolvableType superInterfaceResolvableType = ResolvableType.
        forClass(Children.class) .getInterfaces()[0];
        log.info("supper:"+superInterfaceResolvableType.resolveGenerics()[0]);

    }
}
//2018-06-25 20:45:09,302  INFO [Children.java:25] :  
父类ParameterizedType.getActualTypeArguments:class java.lang.String
//2018-06-25 20:45:09,304  INFO [Children.java:36] :  
父接口ParameterizedType.getActualTypeArguments:class java.lang.Long

spring 中处理泛型参数

@Slf4j
public class SpringResolvableTypeGenericClass {

    private List<String> listString;
    private List<List<String>> listLists;
    private Map<String, Long> maps;
    private Parent<String> parent;

    public Map<String, Long> getMaps() {
        return maps;
    }

    /**
     *  private Parent<String> parent;
     *  parent type:com.wangji.demo.Parent<java.lang.String>
     *  泛型参数为:class java.lang.String
     */
    public static void  doTestFindParent(){
        ResolvableType parentResolvableType = ResolvableType.forField(ReflectionUtils.findField(
                SpringResolvableTypeGenericClass.class,"parent"));
        log.info("parent type:"+parentResolvableType.getType());

        //获取第0个位置的参数泛型
        Class<?> resolve = parentResolvableType.getGeneric(0).resolve();
        log.info("泛型参数为:"+resolve);

    }

    /**
     * private List<String> listString;
     * listString type:java.util.List<java.lang.String>
     * 泛型参数为:class java.lang.String
     */
    public static void  doTestFindListStr(){
        ResolvableType listStringResolvableType = ResolvableType.forField(ReflectionUtils.findField(
                SpringResolvableTypeGenericClass.class,"listString"));
        log.info("listString type:"+listStringResolvableType.getType());

        //获取第0个位置的参数泛型
        Class<?> resolve = listStringResolvableType.getGeneric(0).resolve();
        log.info("泛型参数为:"+resolve);

    }

    /**
     * private List<List<String>> listLists;
     * listLists type:java.util.List<java.util.List<java.lang.String>>
     * 泛型参数为:interface java.util.List
     * 泛型参数为:class java.lang.String
     * 泛型参数为:class java.lang.String
     * begin 遍历
     * 泛型参数为:java.util.List<java.lang.String>
     * end 遍历
     */
    public static void  doTestFindlistLists(){
        ResolvableType listListsResolvableType = ResolvableType.forField(ReflectionUtils.findField(
                SpringResolvableTypeGenericClass.class,"listLists"));
        log.info("listLists type:"+listListsResolvableType.getType());

        //获取第0个位置的参数泛型
        Class<?> resolve = listListsResolvableType.getGeneric(0).resolve();
        log.info("泛型参数为:"+resolve);

        //region 这两种实现方式一样的 泛型参数为:class java.lang.String
        resolve = listListsResolvableType.getGeneric(0).getGeneric(0).resolve();
        log.info("泛型参数为:"+resolve);

        resolve = listListsResolvableType.getGeneric(0,0).resolve();
        log.info("泛型参数为:"+resolve);
        //endregion

        ResolvableType[] resolvableTypes = listListsResolvableType.getGenerics();
        log.info("begin 遍历");
        for(ResolvableType resolvableType: resolvableTypes){
             resolve = resolvableType.resolve();
            log.info("泛型参数为:"+resolve);
        }
        log.info("end 遍历");
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:100] : listLists type:java.util.List<java.util.List<java.lang.String>>
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:104] : 泛型参数为:interface java.util.List
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:107] : 泛型参数为:class java.lang.String
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:110] : 泛型参数为:class java.lang.String
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:113] : begin 遍历
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:116] : 泛型参数为:interface java.util.List
//        2018-06-26 10:02:57,538  INFO [SpringResolvableTypeGenericClass.java:118] : end 遍历

    }

    /**
     *  private Map<String, Long> maps;
     */
    public static void  doTestFindMaps(){
        ResolvableType mapsResolvableType = ResolvableType.forField(ReflectionUtils.findField(
                SpringResolvableTypeGenericClass.class,"maps"));
        log.info("maps type:"+mapsResolvableType.getType());

        log.info("begin 遍历");
        ResolvableType[] resolvableTypes = mapsResolvableType.getGenerics();
        Class<?> resolve =null;
        for(ResolvableType resolvableType: resolvableTypes){
            resolve = resolvableType.resolve();
            log.info("泛型参数为:"+resolve);
        }
        log.info("end 遍历");
//        2018-06-26 10:11:51,833  INFO [SpringResolvableTypeGenericClass.java:144] : maps type:java.util.Map<java.lang.String, java.lang.Long>
//        2018-06-26 10:11:51,833  INFO [SpringResolvableTypeGenericClass.java:146] : begin 遍历
//        2018-06-26 10:11:51,833  INFO [SpringResolvableTypeGenericClass.java:151] : 泛型参数为:class java.lang.String
//        2018-06-26 10:11:51,833  INFO [SpringResolvableTypeGenericClass.java:151] : 泛型参数为:class java.lang.Long
//        2018-06-26 10:11:51,833  INFO [SpringResolvableTypeGenericClass.java:153] : end 遍历

    }

    /**
     * Map<String, Long>
     */
    public static void doTestFindReturn(){
        // Spring的提供工具类,用于方法的返回值的泛型信息
        ResolvableType resolvableType = ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(SpringResolvableTypeGenericClass.class, "getMaps"));
        log.info("maps type:"+resolvableType.getType());
        log.info("begin 遍历");
        ResolvableType[] resolvableTypes = resolvableType.getGenerics();
        Class<?> resolve =null;
        for(ResolvableType resolvableTypeItem: resolvableTypes){
            resolve = resolvableTypeItem.resolve();
            log.info("泛型参数为:"+resolve);
        }
        log.info("end 遍历");
//        2018-06-26 10:18:49,613  INFO [SpringResolvableTypeGenericClass.java:134] : maps type:java.util.Map<java.lang.String, java.lang.Long>
//        2018-06-26 10:18:49,613  INFO [SpringResolvableTypeGenericClass.java:135] : begin 遍历
//        2018-06-26 10:18:49,613  INFO [SpringResolvableTypeGenericClass.java:140] : 泛型参数为:class java.lang.String
//        2018-06-26 10:18:49,613  INFO [SpringResolvableTypeGenericClass.java:140] : 泛型参数为:class java.lang.Long
//        2018-06-26 10:18:49,613  INFO [SpringResolvableTypeGenericClass.java:142] : end 遍历

    }

    /**
     * 总结一句话就是使用起来非常的简单方便,更多超级复杂的可以参考spring 源码中的测试用例:ResolvableTypeTests
     * 其实这些的使用都是在Java的基础上进行使用的哦!
     Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”;其中,“所有类型”的描述尤为值得关注。它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,
     而是从Java语言角度来说,对基本类型、引用类型向上的抽象;
     Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型(Class);
     原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
     参数化类型,就是我们平常所用到的泛型List、Map;
     数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;
     基本类型,也就是我们所说的java的基本类型,即int,float,double等
     * @param args
     */
    public static void main(String[] args) {
        doTestFindParent();
        doTestFindListStr();
        doTestFindlistLists();
        doTestFindMaps();
        doTestFindReturn();
    }
    /**
     言归正传,下面讲解ResolvableType。ResolvableType为所有的java类型提供了统一的数据结构以及API,换句话说,一个ResolvableType对象就对应着一种java类型。我们可以通过ResolvableType对象获取类型携带的信息(举例如下):
     1.getSuperType():获取直接父类型
     2.getInterfaces():获取接口类型
     3.getGeneric(int...):获取类型携带的泛型类型
     4.resolve():Type对象到Class对象的转换

     另外,ResolvableType的构造方法全部为私有的,我们不能直接new,只能使用其提供的静态方法进行类型获取:
     1.forField(Field):获取指定字段的类型
     2.forMethodParameter(Method, int):获取指定方法的指定形参的类型
     3.forMethodReturnType(Method):获取指定方法的返回值的类型
     4.forClass(Class):直接封装指定的类型
     5.ResolvableType.forInstance 获取指定的实例的泛型信息
     */
}

参考文章

项目地址信息

源码

总结

每一次自己讲想要表达的东西总结处理还是非常的难,想要掌握起来十分的棘手,查看spring处理泛型的时候,非常难懂,根基不深入,需要更多的实践去详细了解,多了解之后才能顺手啊!之前看获取父类的泛型虽然知道怎么书写但是不是很理解。

  • 17
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值