java.lang.reflect.Type的简单使用

Type接口,反射包的一个接口。Class类实现了此接口。

主要通过两个Demo来展示Type下的几个实现类:ParameterizedType,TypeVariable,GenericArrayType,WildcardType的简单使用:

TypeDemo:ParameterizedType,TypeVariable,GenericArrayType,WildcardType的方法概略

package DemoReflection;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;

import util.UtilForTest;

public class TypeDemo {

    @SuppressWarnings({ "rawtypes", "unused" })
    public static void main(String[] args) {
        // ParameterizedType
        try {
            Field f = EntityType.class.getDeclaredField("map");
            Type t = f.getGenericType();
            UtilForTest.DisplayStr("getClass--:" + t.getClass());
            UtilForTest.DisplayStr("getOwnerType--:" + ((ParameterizedType)t).getOwnerType());  // 获得拥有者   Map<String,Person> map 这个 ParameterizedType 的 getOwnerType() 为 null,而 Map.Entry<String, String>entry 的 getOwnerType() 为 Map 所属于的 Type。
            UtilForTest.DisplayStr("getRawType--:" + ((ParameterizedType)t).getRawType()); // 如 Map<String,Person> map 这个 ParameterizedType 返回的是 Map 类的全限定类名的 Type。  getRawType--:interface java.util.Map
            UtilForTest.DisplayStr("getActualTypeArguments()[0]--:" + ((ParameterizedType)t).getActualTypeArguments()[0]);// Type[] getActualTypeArguments(); 返回 这个 Type 类型的参数的实际类型数组。 如 Map<String,Person> map 这个 ParameterizedType 返回的是 String 类,Person 类的全限定类名的 Type Array。
            UtilForTest.DisplayStr("getActualTypeArguments()[1]--:" + ((ParameterizedType)t).getActualTypeArguments()[1]);
            
            Field f2 = EntityType.class.getDeclaredField("et");
            Type t2 = f2.getGenericType();
            UtilForTest.DisplayStr("Type.getClass--:" + t2.getClass());
            
            EntityType2 instance = new EntityType2<String>();
            UtilForTest.DisplayStr("EntityType2.getGenericSuperclass.getActualTypeArguments--:" + ((ParameterizedType)instance.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);  //getGenericSuperclass获得父类的Type
            UtilForTest.ergodicDisplayArray("getDeclaredFields--:", instance.getClass().getDeclaredFields());// 通过EntityType2.getDeclaredField是获得不到EntityType中的map属性的,但是确可以获得私有的属性
            UtilForTest.ergodicDisplayArray("getFields--:", instance.getClass().getFields());// 通过EntityType2.getField可以获得父类EntityType中的map属性,无法获得私有的属性
            UtilForTest.DisplayStr("getDeclaredField(\"map\").getGenericType()).getActualTypeArguments()[1]--:" + ((ParameterizedType)instance.getClass().getDeclaredField("map2").getGenericType()).getActualTypeArguments()[1]); 
            Room<String> r = new Room<>();
            System.out.println();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        
        // TypeVariable  和 WildcardType的定义是差不多的  如果是确定的如T则是TypeVariable,如果是不确定?即是一个表达式(包括一个单独的?)则是WildcardType
        try {
            Field fset2 = EntityType2.class.getDeclaredField("set2");
            ParameterizedType pt1 = (ParameterizedType) fset2.getGenericType();
            TypeVariable tv1 = (TypeVariable) pt1.getActualTypeArguments()[0];
            UtilForTest.ergodicDisplayArray("TypeVariable.getBounds()--:", tv1.getBounds()); //获得上边界的数组
            UtilForTest.DisplayStr("getGenericDeclaration()--:" + tv1.getGenericDeclaration()); // 返回的是声明这个 Type 所在的类 的 Type
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        
        // GenericArrayType   数组
        try {
            Field farr = EntityType2.class.getDeclaredField("arr");
            Type type = farr.getGenericType();
            System.out.println("isGenericArrayType--:" + String.valueOf(type instanceof GenericArrayType));
            GenericArrayType genericArrayType = (GenericArrayType) type;
            System.out.println("genericArrayType.getGenericComponentType()--:" + genericArrayType.getGenericComponentType());  // 获得数组元素
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        
        // WildcardType   和 TypeVariable的定义是差不多的  如果是确定的如T则是TypeVariable,如果是不确定?即是一个表达式(包括一个单独的?)则是WildcardType
        try {
            Field fset3 = EntityType2.class.getDeclaredField("set3");
            Type type = ((ParameterizedType)fset3.getGenericType()).getActualTypeArguments()[0];
            System.out.println("isWildcardType--:" + String.valueOf(type instanceof WildcardType));
            WildcardType wildcardType = (WildcardType) type;
            System.out.println(wildcardType.getUpperBounds()[0]); // 上界数组
            Field fset4 = EntityType2.class.getDeclaredField("set4");
            Type type2 = ((ParameterizedType)fset4.getGenericType()).getActualTypeArguments()[0];
            System.out.println("isWildcardType--:" + String.valueOf(type2 instanceof WildcardType));
            WildcardType wildcardType2 = (WildcardType) type2;
            System.out.println(wildcardType2.getUpperBounds()[0]);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }

    }

}
TypeDemo2:  ParameterizedType的附加即与Method的交叉使用

package DemoReflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import util.UtilForTest;

public class TypeDemo2 {
     public static void main(String[] args) {
      // ParameterizedType
         try {
             Field f = EntityType3.class.getDeclaredField("a");
             Type t = f.getGenericType();
             UtilForTest.DisplayStr("getClass--:" + t.getClass());
             UtilForTest.DisplayStr("getOwnerType--:" + ((ParameterizedType)t).getOwnerType());  // 获得拥有者   Map<String,Person> map 这个 ParameterizedType 的 getOwnerType() 为 null,而 Map.Entry<String, String> entry 的 getOwnerType() 为 Map 的 Type。
             UtilForTest.DisplayStr("getRawType--:" + ((ParameterizedType)t).getRawType()); // 如 Map<String,Person> map 这个 ParameterizedType 返回的是 Map 类的全限定类名的 Type。  getRawType--:interface java.util.Map
             UtilForTest.DisplayStr("(Class)getRawType--:" + (Class)(((ParameterizedType)t).getRawType())); // Type是强转为Class是否会报错   不会
             UtilForTest.DisplayStr("(Class)getRawType.isAssignableFrom--:" + Collection.class.isAssignableFrom((Class)(((ParameterizedType)t).getRawType()))); // Type强转为Class是否能判断继承关系
             try {
                List list1 = (ArrayList) ((Class)(((ParameterizedType)t).getRawType())).newInstance();  // Type强转为Class是否能创建实例,这里是因为List是一个接口,所以并不能直接newInstance
                UtilForTest.DisplayStr("(List) ((Class)(((ParameterizedType)t).getRawType())).newInstance().size--:" + ((List) ((Class)(((ParameterizedType)t).getRawType())).newInstance()).size()); // 
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
             UtilForTest.DisplayStr("getActualTypeArguments()[0]--:" + ((ParameterizedType)t).getActualTypeArguments()[0]);// Type[] getActualTypeArguments(); 返回 这个 Type 类型的参数的实际类型数组。 如 Map<String,Person> map 这个 ParameterizedType 返回的是 String 类,Person 类的全限定类名的 Type Array。
             Type t2 = ((ParameterizedType)t).getActualTypeArguments()[0];
             UtilForTest.DisplayStr("getActualTypeArguments()[0] instanceof ParameterizedType --:" + String.valueOf(t2 instanceof ParameterizedType));  // ParameterizedType参数的内部参数还为ParameterizedType依然可以正确得出
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
         } catch (SecurityException e) {
             e.printStackTrace();
         }
         List<String> list = new ArrayList<String>();
         listTest(list);
         list.getClass().isPrimitive();
    }
     
     // 获得方法的参数类型
     public static void listTest(List<String> lists){
         Type t = lists.getClass();
         System.out.println("Start listTest");
         UtilForTest.ergodicDisplayArray("List.class.getFields() --:", lists.getClass().getFields());  // 
         try {
            Method m = TypeDemo2.class.getMethod("listTest", List.class);
            UtilForTest.DisplayStr("getDeclaringClass --:" + String.valueOf(m.getDeclaringClass()));  // 方法定义所在的类
            UtilForTest.ergodicDisplayArray("getParameterTypes() --:" , m.getParameterTypes()); // 方法的各个入参的Class数组
            UtilForTest.DisplayStr("getDefaultValue --:" + String.valueOf(m.getDefaultValue())); // 默认值,涉及到注解,具体是什么不太清楚
            UtilForTest.ergodicDisplayArray("getGenericParameterTypes --:" , m.getGenericParameterTypes()); //方法的各个入参的Type数组
            UtilForTest.DisplayStr("getGenericParameterTypes.toString --:" + m.getGenericParameterTypes()[0].toString());  // type to string
            UtilForTest.DisplayStr("getGenericParameterTypesIsParameterizedType --:" + String.valueOf(m.getGenericParameterTypes()[0] instanceof ParameterizedType));  // 入参是ParameterizedType-true
            UtilForTest.DisplayStr("m.getGenericParameterTypes()[0]. --:" + ((ParameterizedType)m.getGenericParameterTypes()[0]).getActualTypeArguments()[0]); // 见main函数该方法释义
             
            UtilForTest.ergodicDisplayArray("getTypeParameters --:" , m.getTypeParameters());  // TypeVariable 数据    TypeVariable是什么见TypeDemo

            UtilForTest.DisplayStr("toGenericString --:" + String.valueOf(m.toGenericString())); // 方法和入参的全限定名
            UtilForTest.DisplayStr("toString --:" + String.valueOf(m.toString()));  // 入参就不是
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
         UtilForTest.DisplayStr("getParameterizedTypeByParamsInstance --:" + String.valueOf(t instanceof ParameterizedType));  // 在方法内部可获得入参Type
     }
}


之后是一下用以支持以上代码的一些实用类:

EntityType:

package DemoReflection;

import java.util.Map;
import java.util.Set;

public class EntityType<T> {

    public Map<String, T> map;
    
    public Set<T> set;
    
    public EntityType2<T> et;

    /**
     * @return the map
     */
    public Map<String, T> getMap() {
        return map;
    }

    /**
     * @param map the map to set
     */
    public void setMap(Map<String, T> map) {
        this.map = map;
    }

    /**
     * @return the set
     */
    public Set<T> getSet() {
        return set;
    }

    /**
     * @param set the set to set
     */
    public void setSet(Set<T> set) {
        this.set = set;
    }

    /**
     * @return the et
     */
    public EntityType2<T> getEt() {
        return et;
    }

    /**
     * @param et the et to set
     */
    public void setEt(EntityType2<T> et) {
        this.et = et;
    }
    
    
    public void testMethod(String str){
        System.out.println(str);
    }
    
}
EntityType2:

package DemoReflection;

import java.io.Closeable;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;

import javax.management.monitor.StringMonitorMBean;

//public class EntityType2<T extends InputStream & StringMonitorMBean> extends EntityType<T> {
public class EntityType2<T> extends EntityType<T> {

    public Map<String, T> map2;
    
    public Set<T> set2;
    
    private T[] arr;

    public Set<? extends Number> set3;
    
    public Set<?> set4;

    /**
     * @return the map2
     */
    public Map<String, T> getMap2() {
        return map2;
    }

    /**
     * @param map2 the map2 to set
     */
    public void setMap2(Map<String, T> map2) {
        this.map2 = map2;
    }

    /**
     * @return the arr
     */
    public T[] getArr() {
        return arr;
    }

    /**
     * @param arr the arr to set
     */
    public void setArr(T[] arr) {
        this.arr = arr;
    }

    /**
     * @return the set2
     */
    public Set<T> getSet2() {
        return set2;
    }

    /**
     * @param set2 the set2 to set
     */
    public void setSet2(Set<T> set2) {
        this.set2 = set2;
    }

    /**
     * @return the set3
     */
    public Set<? extends Number> getSet3() {
        return set3;
    }

    /**
     * @param set3 the set3 to set
     */
    public void setSet3(Set<? extends Number> set3) {
        this.set3 = set3;
    }

    /**
     * @return the set4
     */
    public Set<?> getSet4() {
        return set4;
    }

    /**
     * @param set4 the set4 to set
     */
    public void setSet4(Set<?> set4) {
        this.set4 = set4;
    }
    
    
    private void testMethod2(String str){
        System.out.println(str);
    }
    

    protected void testMethod3(String str){
        System.out.println(str);
    }
    
    void testMethod4(String str){
        System.out.println(str);
    }
}
EntityType3:

package DemoReflection;


import java.util.ArrayList;
import java.util.List;


public class EntityType3 {


    private List<List<String>> a = new ArrayList<>();
    
    private Object o;


    /**
     * @return the a
     */
    public List<List<String>> getA() {
        return a;
    }


    /**
     * @param a the a to set
     */
    public void setA(List<List<String>> a) {
        this.a = a;
    }


    /**
     * @return the o
     */
    public Object getO() {
        return o;
    }


    /**
     * @param o the o to set
     */
    public void setO(Object o) {
        this.o = o;
    }
}

用来展示的UtilForTest:

package util;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class UtilForTest {

    /**
     * 
     * 功能描述: <br>
     * 遍历显示数组,末尾会加一个空白行
     *
     * @param desc  每行数组的统一注释
     * @param arr   数组对象
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static <T> void ergodicDisplayArray(String desc, T[] arr) {
        if (arr.length == 0) {
            System.out.println(desc + "数组长度为0");
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println("Array:--" + desc + arr[i]);
        }
        System.out.println();
    }
    /**
     * 
     * 功能描述: <br>
     * 显示字符串并加一个空白行
     *
     * @param str
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static <T> void DisplayStr(String str) {
            System.out.println("String:--" + str);
            System.out.println();
    }
    
    /**
     * 
     * 功能描述: <br>
     * 遍历显示集合,末尾会加一个空白行
     *
     * @param desc  每行数组的统一注释
     * @param arr   数组对象
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static <T> void ergodicDisplayCollection(Collection<T> collection) {
        if (collection instanceof List || collection instanceof Set) {
            for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
                T t = (T) iterator.next();
                System.out.println(t);
            }
        }
        System.out.println();
    }
    
    /**
     * 
     * 功能描述: <br>
     * 遍历显示集合,末尾会加一个空白行
     *
     * @param desc  每行数组的统一注释
     * @param arr   数组对象
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static <K, V> void ergodicDisplayMap(Map<K, V> map) {
        for (Entry<K, V> e : map.entrySet()) {
            System.out.println(e.getKey() + " : " + e.getValue());
        }
        System.out.println();
    }
    
    /**
     * 
     * 功能描述: <br>
     * 遍历显示集合,末尾会加一个空白行
     *
     * @param desc  每行数组的统一注释
     * @param arr   数组对象
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static <T, K, V> void ergodicDisplay(String desc, Object obj) {
        System.out.println(desc);
        try {
            if (obj instanceof Collection<?>) {
                ergodicDisplayCollection((Collection<?>) obj);
            }
            if (obj instanceof Map<?, ?>) {
                ergodicDisplayMap((Map<?, ?>) obj);
            }
            if (obj.getClass().isArray()) {
                ergodicDisplayArray("",(T[]) obj);
            }
        } catch (Exception e) {
            System.out.println(desc + "格式错误,请确定格式");
        }
    }
}

参考:谈谈Java类型中ParameterizedType,GenericArrayType,TypeVariabl,WildcardType

           Type Java类型

           提炼Java Reflection

           java Type 详解

发布了29 篇原创文章 · 获赞 11 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/yue_hu/article/details/79170497
今日推荐