通过反射获取属性类型

  • 1.构造函数中的属性
  • 举个栗子
  • 2.成员变量的属性
  • 栗子
  • 3.成员方法中的属性
  • 举个栗子
  • 4.注
  • 探讨通过反射能否获取到泛型的运行时类型


Java中反射可以创建构造函数、获取属性和获取方法,这三个地方都有属性的参与,同时也都提供了属性获取的方法。本文就学习一些这三块中获取属性的方法。

1.构造函数中的属性

返回值

Constructor中获取属性类型的方法

用途

Class<?>[]

getExceptionTypes()

获取构造函数的抛出的异常类型的限定类型数组

Type[]

getGenericExceptionTypes()

获取构造函数的抛出的异常类型的原始类型数组

Type[] (声明类型/参数类型)

getGenericParameterTypes()

属性不是泛型,返回getParameterTypes的值;如果含泛型,返回参数类型。最后整理成数组返回

Class<?>[] 声明类型/接口类型)

getParameterTypes()

属性不是泛型,返回声明类型;如果含泛型,返回接口类型。最后整理成数组返回

TypeVariable<Constructor>[]

getTypeParameters()

获取类一共都用了哪些泛型参数

上面的用途是我自己意译的,通过栗子理解一下

举个栗子

类:

public class ClassBean {

    private String classname;
    public ClassBean(String classname) throws ArrayIndexOutOfBoundsException {
        this.classname = classname;
    }

    private List<String> students;
    public <T extends Throwable> ClassBean(List<String> students) throws T, NullPointerException {
        this.students = students;
    }
}

调用:

Class clazz = Class.forName("com.example.myapplication.bean.ClassBean");
            Constructor[] constructors = clazz.getConstructors();

            for (int y = 0; y < constructors.length; y++) {

                System.out.println("************ constructors[" + y + "] ************ start");

                System.out.println("============== getExceptionTypes ============== ");
                Class<?>[] classes = constructors[y].getExceptionTypes();
                for (int i = 0; i < classes.length; i++) {
                    System.out.println("classes[" + i + "] ==" + classes[i]);
                }

                System.out.println("============== getGenericExceptionTypes ============== ");
                Type[] types = constructors[y].getGenericExceptionTypes();
                for (int i = 0; i < types.length; i++) {
                    System.out.println("types[" + i + "] ==" + types[i]);
                }

                System.out.println("============== getGenericParameterTypes ============== ");
                Type[] types2 = constructors[y].getGenericParameterTypes();
                for (int i = 0; i < types2.length; i++) {
                    System.out.println("types[" + i + "] ==" + types2[i]);
                }

                System.out.println("============== getParameterTypes ============== ");
                Class<?>[] classes2 = constructors[y].getParameterTypes();
                for (int i = 0; i < classes2.length; i++) {
                    System.out.println("classes[" + i + "] ==" + classes2[i]);
                }

                System.out.println("============== getTypeParameters ============== ");
                TypeVariable[] typeParameters = constructors[0].getTypeParameters();
                for (int i = 0; i < typeParameters.length; i++) {
                    System.out.println("typeParameters[" + i + "] ==" + typeParameters[i]);
                }

                System.out.println("************ constructors[" + y + "] ************ end");
                System.out.println(" ");
                System.out.println(" ");
                System.out.println(" ");
            }

输出:

I/System.out: ************ constructors[0] ************ start
 I/System.out: ============== getExceptionTypes ============== 
 I/System.out: classes[0] ==class java.lang.ArrayIndexOutOfBoundsException
 
 I/System.out: ============== getGenericExceptionTypes ============== 
 I/System.out: types[0] ==class java.lang.ArrayIndexOutOfBoundsException
 
 I/System.out: ============== getGenericParameterTypes ============== 
 I/System.out: types[0] ==class java.lang.String
 
 I/System.out: ============== getParameterTypes ============== 
 I/System.out: classes[0] ==class java.lang.String
 
 I/System.out: ============== getTypeParameters ============== 
 I/System.out: ************ constructors[0] ************ end



 I/System.out: ************ constructors[1] ************ start
 I/System.out: ============== getExceptionTypes ============== 
 I/System.out: classes[0] ==class java.lang.Throwable
 I/System.out: classes[1] ==class java.lang.NullPointerException
 
 I/System.out: ============== getGenericExceptionTypes ============== 
 I/System.out: types[0] ==T
 I/System.out: types[1] ==class java.lang.NullPointerException
 
 I/System.out: ============== getGenericParameterTypes ============== 
 I/System.out: types[0] ==java.util.List<java.lang.String>
 
 I/System.out: ============== getParameterTypes ============== 
 I/System.out: classes[0] ==interface java.util.List
 
 I/System.out: ============== getTypeParameters ============== 
 I/System.out: ************ constructors[1] ************ end

2.成员变量的属性

返回值

Feild的方法

用途

Type

getGenericType()

如果属性不是泛型,返回getType的值;如果含泛型,返回参数类型

Class

getType()

如果属性不是泛型,返回声明类型;如果含泛型,返回接口类型

栗子

public class ClassBean<R> {
    private String classname;
    private List<String> students;
    private List<?> list;
    private R r;
}
Class clazz = Class.forName("com.example.myapplication.bean.ClassBean");

            Field field_classname = clazz.getDeclaredField("classname");
            Field field_students = clazz.getDeclaredField("students");
            Field field_list = clazz.getDeclaredField("list");
            Field field_r = clazz.getDeclaredField("r");

            System.out.println("field_classname getGenericType ==" + field_classname.getGenericType());
            System.out.println("field_classname getType ==" + field_classname.getType());
            System.out.println("field_students getGenericType ==" + field_students.getGenericType());
            System.out.println("field_students getType ==" + field_students.getType());
            System.out.println("field_list getGenericType ==" + field_list.getGenericType());
            System.out.println("field_list getType ==" + field_list.getType());
            System.out.println("field_r getGenericType ==" + field_r.getGenericType());
            System.out.println("field_r getType ==" + field_r.getType());

输出

I/System.out: field_classname getGenericType ==class java.lang.String
 I/System.out: field_classname getType ==class java.lang.String
 
 I/System.out: field_students getGenericType ==java.util.List<java.lang.String>
 I/System.out: field_students getType ==interface java.util.List
 
 I/System.out: field_list getGenericType ==java.util.List<?>
 I/System.out: field_list getType ==interface java.util.List
 
 I/System.out: field_r getGenericType ==R
 I/System.out: field_r getType ==class java.lang.Object

3.成员方法中的属性

Method 的方法其中五个和构造函数的一样,又多出两个返回值的函数。

返回值

Method 中获取属性类型的方法

用途

Class<?>[]

getExceptionTypes()

获取Method 函数的抛出的异常类型的限定类型数组

Type[]

getGenericExceptionTypes()

获取Method 函数的抛出的异常类型的原始类型数组

Type[]

getGenericParameterTypes()

如果属性不是泛型,返回getParameterTypes的值;如果含泛型,返回参数类型。最后整理成数组返回

Class<?>[]

getParameterTypes()

如果属性不是泛型,返回声明类型;如果含泛型,返回接口类型。最后整理成数组返回

Type

getGenericReturnType()

如果属性不是泛型,返回getReturnType的值;如果含泛型,返回参数类型

Class

getReturnType()

如果属性不是泛型,返回声明类型;如果含泛型,返回接口类型

TypeVariable<Constructor>[]

getTypeParameters()

获取类一共都用了哪些泛型参数

举个栗子

目标类:

public class ClassBean<R> {
    public void start(List<String> stringList) {
    }
    public void stop(List<?> list) {
    }
}

调用:

//构造方法中的参数类型
            Class clazz = Class.forName("com.example.myapplication.bean.ClassBean");

            for (int y = 0; y < clazz.getMethods().length; y++) {

                System.out.println("************ getMethods[" + y + "] ************ start");
				System.out.println("方法名称:"+clazz.getMethods()[y].getName());
                System.out.println("============== getExceptionTypes ============== ");
                Class<?>[] classes = clazz.getMethods()[y].getExceptionTypes();
                for (int i = 0; i < classes.length; i++) {
                    System.out.println("classes[" + i + "] ==" + classes[i]);
                }

                System.out.println("============== getGenericExceptionTypes ============== ");
                Type[] types = clazz.getMethods()[y].getGenericExceptionTypes();
                for (int i = 0; i < types.length; i++) {
                    System.out.println("types[" + i + "] ==" + types[i]);
                }

                System.out.println("============== getGenericParameterTypes ============== ");
                Type[] types2 = clazz.getMethods()[y].getGenericParameterTypes();
                for (int i = 0; i < types2.length; i++) {
                    System.out.println("types[" + i + "] ==" + types2[i]);
                }

                System.out.println("============== getParameterTypes ============== ");
                Class<?>[] classes2 = clazz.getMethods()[y].getParameterTypes();
                for (int i = 0; i < classes2.length; i++) {
                    System.out.println("classes[" + i + "] ==" + classes2[i]);
                }

                System.out.println("============== getTypeParameters ============== ");
                TypeVariable[] typeParameters = clazz.getMethods()[0].getTypeParameters();
                for (int i = 0; i < typeParameters.length; i++) {
                    System.out.println("typeParameters[" + i + "] ==" + typeParameters[i]);
                }

                System.out.println("============== getReturnType ============== ");
                Class<?> classes3 = clazz.getMethods()[y].getReturnType();
                System.out.println("ReturnType ==" + classes3);

                System.out.println("============== getGenericReturnType ============== ");
                Type type3 = clazz.getMethods()[y].getGenericReturnType();
                System.out.println("GenericReturnType ==" + type3);

                System.out.println("************ getMethods[" + y + "] ************ end");
                System.out.println(" ");
                System.out.println(" ");
                System.out.println(" ");
            }

输出:(不止如上两个方法哈,其他方法的打印省略了)

I/System.out: ************ getMethods[5] ************ start
 I/System.out: 方法名称:start
 I/System.out: ============== getExceptionTypes ============== 
 I/System.out: ============== getGenericExceptionTypes ============== 
 I/System.out: ============== getGenericParameterTypes ============== 
 I/System.out: types[0] ==java.util.List<java.lang.String>
 I/System.out: ============== getParameterTypes ============== 
 I/System.out: classes[0] ==interface java.util.List
 I/System.out: ============== getTypeParameters ============== 
 I/System.out: ============== getReturnType ============== 
 I/System.out: ReturnType ==void
 I/System.out: ============== getGenericReturnType ============== 
 I/System.out: GenericReturnType ==void
 I/System.out: ************ getMethods[5] ************ end
 I/System.out:  

 I/System.out:  
 I/System.out: ************ getMethods[6] ************ start
 I/System.out: 方法名称:stop
 I/System.out: ============== getExceptionTypes ============== 
 I/System.out: ============== getGenericExceptionTypes ============== 
 I/System.out: ============== getGenericParameterTypes ============== 
 I/System.out: types[0] ==java.util.List<?>
 I/System.out: ============== getParameterTypes ============== 
 I/System.out: classes[0] ==interface java.util.List
 I/System.out: ============== getTypeParameters ============== 
 I/System.out: ============== getReturnType ============== 
 I/System.out: ReturnType ==void
 I/System.out: ============== getGenericReturnType ============== 
 I/System.out: GenericReturnType ==void
 I/System.out: ************ getMethods[6] ************ end

4.注

首先明确一点的是参数类型和参数化类型,他们是不一样的,完全是两个东西。参数类型是指一个属性定义时的类型,参数化类型指的是ParameterizedType。

声明类型指的是不带泛型的部分,如List<?>中的interface java.util.List部分。

探讨通过反射能否获取到泛型的运行时类型

为什么会探讨反射是否能获取到泛型的运行时类型呢?

因为Java有泛型擦除,所以只能尝试通过反射获取泛型的运行时类型。

待续 +