通过反射获取属性类型
- 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有泛型擦除,所以只能尝试通过反射获取泛型的运行时类型。
待续 +