Java reflect Type类及其子类用法分析

来源:互联网 发布:网络女主播谈恋爱 编辑:程序博客网 时间:2024/06/05 06:20

在看源码之前我们先来了解一下什么是Type

首先:Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型(Class)、参数化类型(Parameterized)、数组类型(GenericArrayType)、类型变量(TypeVariable)和基本类型(Class)。

首先我们先来看看其定义:

public interface Type {    default String getTypeName() {//返回一个字符串描述该类型        return toString();    }}
我们再来看看其继承体系


根据类图我们可以看到Type拥有4个已知的子类:

GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。 

ParameterizedType 表示参数化类型,如 Collection<String>

TypeVariable 是各种类型变量的公共高级接口。

WildcardType 表示一个通配符类型表达式,如 ?? extends Number? super Integer。 

以上为JDK API中的解释,看了似乎并没有搞明白其想说明什么

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

A.首先我们看一下ParameterizedType的接口定义

/** * ParameterizedType表示参数化类型,也就是泛型,例如List<T>、Set<T>等; */public interface ParameterizedType extends Type {    //获取泛型中的实际类型,可能会存在多个泛型,例如Map<K,V>,所以会返回Type[]数组;    Type[] getActualTypeArguments();    //获取声明泛型的类或者接口,也就是泛型中<>前面的那个值;    Type getRawType();        //通过getOwnerType()方法可以获取到内部类的“拥有者”;    //拥有者表示的含义--内部类的“父类”,例如: Map  就是 Map.Entry<K,V>的拥有者。    Type getOwnerType();}
例子:

在下面的例子中ParamterizedType类拥有两个成员变量List<T> ,Set<String>我们获取到该类型之后会发现,他们都是ParamterizedTypeImpl类型,因为Set<String>和Set<Integer>实际上是一样的,都是泛型。

public class ParameterizedTypeTest<T> {    private List<T> list=null;    private Set<String> set=null;    public static void main(String[] args) throws NoSuchFieldException{        Field fieldList=ParameterizedTypeTest.class.getDeclaredField("list");        //获取该属性的泛型类型        Type typeList=fieldList.getGenericType();        //获取实际的Type类型        System.out.println(typeList.getClass().getName());  //输出为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl        Field fieldSet=ParameterizedTypeTest.class.getDeclaredField("set");        //获取该属性的泛型类型        Type typeSet=fieldList.getGenericType();        //获取实际的Type类型        System.out.println(typeSet.getClass().getName());  //输出为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl    }}

我们再来看看其接口方法

首先是getActualTypeArguments  : 根据名称,其实也可以猜出其作用:就是获取泛型参数的实际类型。有一点需要注意的是,Java的泛型采用的是擦除发实现了,那么在运行时又能动态的获取泛型的实际类型,就足以证明,泛型类型还是通过某种方式写入到了class文件中

例子如下:

public class ParameterizedTypeTest<T> {    private List<T> list=null;    private Set<Integer> set=null;    private Map<String,Integer> map=null;    private Map<Map<String,Integer>,Map<Object,Object>> map2=null;    /**     * 如果是ParameterizedTypeTest.class.getDeclaredField("map2");     * 那么结果如下:     * System.out.println(types[0]);  //输出为:java.util.Map<java.lang.String, java.lang.Integer>     * System.out.println(types[1]);  //输出为:java.util.Map<java.lang.Object, java.lang.Object>     */    public static void testGetActualTypeArguments()throws NoSuchFieldException{        Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("map");        Type typeMap=fieldMap.getGenericType();        ParameterizedType parameterizedTypeMap=(ParameterizedType)typeMap;        Type[] types=parameterizedTypeMap.getActualTypeArguments();        System.out.println(types[0]);   //输出为:class java.lang.String        System.out.println(types[1]);  //输出为:class java.lang.Integer    }    public static void main(String[] args) throws NoSuchFieldException{        testGetActualTypeArguments();    }}
再来看看getRawType方法:获取声明泛型的类或者接口,说明了也就是这个泛型是被谁声明的,例子如下:

public class ParameterizedTypeTest<T> {    private List<T> list=null;    private Set<Integer> set=null;    private Map<String,Integer> map=null;    @Test    public void testGetRawType() throws NoSuchFieldException{        Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("map");        //getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型        Type typeMap=fieldMap.getGenericType();        ParameterizedType parameterizedTypeMap= (ParameterizedType) typeMap;        Type type=parameterizedTypeMap.getRawType();        System.out.println(type.getTypeName()); //输出  java.util.Map    }}

最后再来getOwnerType()方法

public class ParameterizedTypeTest<T> {    private Map.Entry<String,Integer> mapEntry;    @Test    public void testGetRawType() throws NoSuchFieldException{        Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("mapEntry");        //getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型        Type typeMap=fieldMap.getGenericType();        ParameterizedType parameterizedTypeMap= (ParameterizedType) typeMap;        Type type=parameterizedTypeMap.getRawType();        System.out.println(type.getTypeName()); //输出  java.util.Map$Entry        System.out.println(parameterizedTypeMap.getOwnerType());    //输出   interface java.util.Map    }}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

再来看看GenericArrayType

首先先看看定义

/** * 泛型数组类型,例如List<String>[] 、T[]等 */public interface GenericArrayType extends Type {    /**     * 返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、     * T[] 中的T(TypeVariableImpl)     */    Type getGenericComponentType();}
例子:

public class GenericArrayTypeTest<T> {    private T[] t;    private List<String>[] listArray;    @Test    public void TestGetGenericComponentType()throws NoSuchFieldException{        Field fieldListArray=GenericArrayTypeTest.class.getDeclaredField("listArray");        Type typeListArray=fieldListArray.getGenericType();        System.out.println(typeListArray.getClass().getName()); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl        Field fieldT =GenericArrayTypeTest.class.getDeclaredField("t");        Type typeT=fieldT.getGenericType();        System.out.println(typeT.getClass().getName());         //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl    }   }

通过上述例子可以看出:GenericArrayType表示的是泛型数组类型

再来看看其接口方法:getGenericComponentType

public class GenericArrayTypeTest<T> {    private T[] t;    private List<String>[] listArray;        public void TestGetGenericComponentType(String filedName)throws NoSuchFieldException{        Field fieldListArray=GenericArrayTypeTest.class.getDeclaredField(filedName);        Type typeListArray=fieldListArray.getGenericType();        GenericArrayType genericArrayType=(GenericArrayType)typeListArray;        Type type=genericArrayType.getGenericComponentType();        System.out.println(type.getTypeName());    }    @Test    public void print()throws NoSuchFieldException{        TestGetGenericComponentType("listArray");   //输出 java.util.List<java.lang.String>        TestGetGenericComponentType("t");           //输出 T    }}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

再来看看TypeVariable

/** * 泛型的类型变量,指的是List<T>、Map<K,V>中的T,K,V等值, * 实际的Java类型是TypeVariableImpl(TypeVariable的子类); * 此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限; */interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {    /**     * 获得该类型变量的上限,也就是泛型中extend右边的值;     * 例如 List<T extends Number> ,Number就是类型变量T的上限;     * 如果我们只是简单的声明了List<T>(无显式定义extends),那么默认为Object;     * 值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接,     * 例如 List<T extends Number & Serializable>;其中,& 后必须为接口;     */    Type[] getBounds();    //获取声明该类型变量实体    D getGenericDeclaration();    //获取类型变量在源码中定义的名称;    String getName();    //这个方法是JDK1.8中的新方法,目前还不清楚其作用    AnnotatedType[] getAnnotatedBounds();}
先来看看用法:

public class TypeVariableTest<T> {    private List<T> list;    @Test    public void testTypeVariable()throws NoSuchFieldException{        Field fieldList=TypeVariableTest.class.getDeclaredField("list");        Type typeList=fieldList.getGenericType();        ParameterizedType parameterizedTypeList=(ParameterizedType)typeList;        Type[] types=parameterizedTypeList.getActualTypeArguments();        System.out.println(types[0].getClass().getName());      //输出    sun.reflect.generics.reflectiveObjects.TypeVariableImpl    }}
再来看看getBounds()方法

public class TypeVariableTest<T extends Number & Serializable & Comparable> {   private T t;    @Test    public void testGetBounds()throws NoSuchFieldException{        Field fieldT=TypeVariableTest.class.getDeclaredField("t");        TypeVariable typeVariable= (TypeVariable) fieldT.getGenericType();        Type[] types=typeVariable.getBounds();        for(Type type : types){            System.out.print(type + " ");     //输出 class java.lang.Number interface java.io.Serializable interface java.lang.Comparable         }    }}

默认的边界测试

public class TypeVariableTest<T> {    private List<T> list;    @Test    public void testTypeVariable()throws NoSuchFieldException{        Field fieldList=TypeVariableTest.class.getDeclaredField("list");        Type typeList=fieldList.getGenericType();        ParameterizedType parameterizedTypeList=(ParameterizedType)typeList;        Type[] types=parameterizedTypeList.getActualTypeArguments();        TypeVariable typeVariable=(TypeVariable)types[0];        Type[] types2=typeVariable.getBounds();        for(Type type : types2){            System.out.print(type + " ");     //输出 class java.lang.Object         }    }}

再来看看getGenericDeclaration方法

public class TypeVariableTest<T> {    private T t;    @Test   //获取声明该类型变量实体,也就是TypeVariableTest<T>中的TypeVariableTest;    public void testGetGenericDeclaration()throws NoSuchFieldException{        Field fieldT=TypeVariableTest.class.getDeclaredField("t");        TypeVariable typeVariable=(TypeVariable)fieldT.getGenericType();        GenericDeclaration genericDeclaration=typeVariable.getGenericDeclaration();        System.out.println(genericDeclaration);     //输出 class TypeVariableTest    }}

里面涉及到了一个类 GenericDeclaration  顺便看看该类

含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型);该类的继承结构如下:

也就是说,只有在以上三种子类中才可以定义泛型

public class TestGenericDeclarationForClass<T> {        //测试在Class定义泛型}class TestGenericDeclarationForConstruct{    public <T> TestGenericDeclarationForConstruct(T t){        //测试在构造方法定义泛型    }}class TestGenericDeclarationForMethod{    public <T> void test(T t){        //测试在方法定义泛型    }}
再来看看方法getName  这个方法就比较好理解了

public class TypeVariableTest<T> {    private T t;    @Test    public void testGetName()throws NoSuchFieldException{        Field fieldT=TypeVariableTest.class.getDeclaredField("t");        TypeVariable typeVariable=(TypeVariable)fieldT.getGenericType();        System.out.println(typeVariable.getName()); //输出 T    }}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

再来看看Class类 (Class 类就不是接口,而是实现类了)

Type接口的实现类,是我们工作中常用到的一个对象;在Java中,每个.class文件在程序运行期间,都对应着一个Class对象,这个对象保存有这个类的全部信息;因此,Class对象也称之为Java反射的基础;

public class ClassTest {    private ClassTest classTest;    @Test    public void testClass()throws NoSuchFieldException{        Field field=ClassTest.class.getDeclaredField("classTest");        Type type=field.getGenericType();        System.out.println(type);   //class ClassTest    }}

当我们没有声明泛型的时候,我们普通的对象就是一个Class类型,是Type中的一种;

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

最后再来看看 WildcardType

定义如下:

/** * 通配符表达式,表示通配符泛型 * 例如:List<? extends Number> 和 List<? super Integer>; */public interface WildcardType extends Type {    //获取泛型变量的上边界(extends)    Type[] getUpperBounds();    //获取泛型变量的下边界(super)    Type[] getLowerBounds();}
获取该对象例子:

public class WildcardTypeTest {    private List<? extends Number> listNum;    private List<? super String> listStr;    public void testWildcardType(String fieldName)throws NoSuchFieldException{        Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName);        ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType();        Type[] types=parameterizedTypeNum.getActualTypeArguments();        System.out.println(types[0].getClass());    }    @Test    public void print()throws NoSuchFieldException{        testWildcardType("listNum");    //输出 class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl        testWildcardType("listStr");    //输出 class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl    }}

在来看看方法getUpperBounds()

public class WildcardTypeTest {    private List<? extends Number> listNum;    private List<? super String> listStr;    public void testWildcardType(String fieldName)throws NoSuchFieldException{        Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName);        ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType();        Type[] types=parameterizedTypeNum.getActualTypeArguments();        WildcardType wildcardType=(WildcardType)types[0];        System.out.println(wildcardType.getUpperBounds()[0]);        //System.out.println(wildcardType.getLowerBounds()[0]);    }    @Test    public void print()throws NoSuchFieldException{        testWildcardType("listNum");    //输出 class java.lang.Number    }}

最后再来看看方法getLowerBounds()

public class WildcardTypeTest {    private List<? extends Number> listNum;    private List<? super String> listStr;    public void testWildcardType(String fieldName)throws NoSuchFieldException{        Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName);        ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType();        Type[] types=parameterizedTypeNum.getActualTypeArguments();        WildcardType wildcardType=(WildcardType)types[0];        //System.out.println(wildcardType.getUpperBounds()[0]);        System.out.println(wildcardType.getLowerBounds()[0]);    }    @Test    public void print()throws NoSuchFieldException{        testWildcardType("listStr");    //输出 class java.lang.String    }}