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

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

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

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

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

Java reflect Type类及其子类用法分析_第1张图片


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

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

ParameterizedType 表示参数化类型,如 Collection

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

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

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

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

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

/**
 * ParameterizedType表示参数化类型,也就是泛型,例如List、Set等;
 */
public interface ParameterizedType extends Type {

    //获取泛型中的实际类型,可能会存在多个泛型,例如Map,所以会返回Type[]数组;
    Type[] getActualTypeArguments();

    //获取声明泛型的类或者接口,也就是泛型中<>前面的那个值;
    Type getRawType();
    
    //通过getOwnerType()方法可以获取到内部类的“拥有者”;
    //拥有者表示的含义--内部类的“父类”,例如: Map  就是 Map.Entry的拥有者。
    Type getOwnerType();
}
例子:

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

public class ParameterizedTypeTest {
    private List list=null;
    private Set 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 {
    private List list=null;
    private Set set=null;
    private Map map=null;
    private Map,Map> map2=null;

    /**
     * 如果是ParameterizedTypeTest.class.getDeclaredField("map2");
     * 那么结果如下:
     * System.out.println(types[0]);  //输出为:java.util.Map
     * System.out.println(types[1]);  //输出为:java.util.Map
     */
    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 {
    private List list=null;
    private Set set=null;
    private Map 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 {

    private Map.Entry 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[] 、T[]等
 */
public interface GenericArrayType extends Type {
    /**
     * 返回泛型数组中元素的Type类型,即List[] 中的 List(ParameterizedTypeImpl)、
     * T[] 中的T(TypeVariableImpl)
     */
    Type getGenericComponentType();
}
例子:

public class GenericArrayTypeTest {

    private T[] t;
    private List[] 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 {

    private T[] t;
    private List[] 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
        TestGetGenericComponentType("t");           //输出 T
    }
}

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

再来看看TypeVariable

/**
 * 泛型的类型变量,指的是List、Map中的T,K,V等值,
 * 实际的Java类型是TypeVariableImpl(TypeVariable的子类);
 * 此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;
 */
interface TypeVariable extends Type, AnnotatedElement {

    /**
     * 获得该类型变量的上限,也就是泛型中extend右边的值;
     * 例如 List ,Number就是类型变量T的上限;
     * 如果我们只是简单的声明了List(无显式定义extends),那么默认为Object;
     * 值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接,
     * 例如 List;其中,& 后必须为接口;
     */
    Type[] getBounds();

    //获取声明该类型变量实体
    D getGenericDeclaration();

    //获取类型变量在源码中定义的名称;
    String getName();

    //这个方法是JDK1.8中的新方法,目前还不清楚其作用
    AnnotatedType[] getAnnotatedBounds();
}
先来看看用法:

public class TypeVariableTest {
    private List 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 {
   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 {
    private List 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 {
    private T t;

    @Test   //获取声明该类型变量实体,也就是TypeVariableTest中的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 {
        //测试在Class定义泛型
}

class TestGenericDeclarationForConstruct{
    public  TestGenericDeclarationForConstruct(T t){
        //测试在构造方法定义泛型
    }
}

class TestGenericDeclarationForMethod{

    public  void test(T t){
        //测试在方法定义泛型
    }
}
再来看看方法getName  这个方法就比较好理解了

public class TypeVariableTest {
    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 和 List;
 */
public interface WildcardType extends Type {

    //获取泛型变量的上边界(extends)
    Type[] getUpperBounds();

    //获取泛型变量的下边界(super)
    Type[] getLowerBounds();
}
获取该对象例子:

public class WildcardTypeTest {
    private List listNum;

    private List 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 listNum;

    private List 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 listNum;

    private List 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
    }
}









你可能感兴趣的:(Type,WildcardType,TypeVariable)