转自http://uuhorse.iteye.com/blog/1706466
反射API使得Java语言更易实现运行时的动态性,获取Java程序在运行时刻的内部结构,如Java列中的构造方法、域和方法等。反射API的主要功能包括:
① 确定一个对象的类② 取出类的修饰符(modifiers),字段,方法,构造器和超类
③ 找出某个接口里定义的常量和方法说明
④ 创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象)
⑤ 取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做倒。
⑥ 在运行时刻调用动态对象的方法
⑦ 创建数组,数组大小和类型在运行时刻才确定。也能更改数组成员的值。
① 获取对象的类(Class对象)
Class c = obj.getClass();
② 获取一个类的超类
Class sc = c.getSuperclass();
③ 获取类的名字
Class c = obj.getClass();
String name = c.getName();
④ 获取类的修饰符
Class c = obj.getClass();
int m = c.getModifiers();
此处getModifiers()方法返回的是个整型的结果,结果m并不具体表示哪一种修饰符。先看java.lang.reflect.Modifier类,该类对修饰符进行了相应的包装。
类Modifier中定义了一系列的类描述符常量:Modifier.ABSTRACT、Modifier.FINAL、Modifier.PUBLIC等。getModifiers()方法返回的即是类的所有修饰符分别对应的整型值的或运算结果。
如public abstract class MyClass{},new MyClass().getClass().getModfiers()即得到Modifier.ABSTRACT | Modifier.PUBLIC。
同时Modifier类提供了一些列的方法,用于判断getModifiers()返回的整型数字中包含的类修饰符:Modifier.isPublic(m)、Modifier.isAbstract(m)、Modifier.isFinal(m)等。
public class Point {
private int x;
private int y;
private String s1 ="ball";
private String s2="hubin";
private String s3="zhangxiaoxiang";
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
// 分析类的修饰符
public static void printModifiers(Object obj) {
System.out.print("Modifier: \n");
Class c = obj.getClass();
int m = c.getModifiers();
if (Modifier.isPublic(m))
System.out.print("public \n");
if (Modifier.isAbstract(m))
System.out.print("abstract \n");
if (Modifier.isFinal(m))
System.out.print("final \n");
System.out.println(c.getName());
}
public static void main(String[] args) throws Exception {
Point pt1 = new Point(3, 5);
printModifiers(pt1);
}
输出结果:
Modifier:
public
reflect.Point
⑤ 确定一个类实现的接口
Class[] theInterfaces = c.getInterfaces();
从上面的语句中可以看到,接口在反射的API中也是用Class表示的,接口是一种特殊的抽象类。可以使用Class类的isInterface()方法判断一个Class类型是一个类还是接口。
// 分析类的接口
public static void printInterfaceNames(Object o) {
Class c = o.getClass();
Class[] theInterfaces = c.getInterfaces();
for (int i = 0; i < theInterfaces.length; i++) {
String interfaceName = theInterfaces[i].getName();
System.out.println(interfaceName);
}
}
// 判断接口
public static void verifyInterface(Class c) {
String name = c.getName();
if (c.isInterface()) {
System.out.println(name + " 是接口.");
} else {
System.out.println(name + " 是类.");
}
}
⑥ 获取类的字段
一个类的字段(Field)可能来自本类、父类、实现的接口或者接口的接口,可以使用Class对象的getFields()方法获取类中所有的public属性的字段的数组(Field对象数组)。Field对象提供方法取得字段的名字、类型和描述符,甚至可以给字段赋值或者取字段的值。当然,Class类对象提供了getDeclaredFields()方法获取包括public属性在内的所有在类中声明了的域。
// 分析类的字段
public static void printFieldNames(Object o) {
Class c = o.getClass();
//public的字段
Field[] publicFields = c.getFields();
for (int i = 0; i < publicFields.length; i++) {
String fieldName = publicFields[i].getName();
Class typeClass = publicFields[i].getType();
String fieldType = typeClass.getName();
System.out.println("字段名: " + fieldName + ", 类型: " + fieldType);
}
//所有的字段
Field[] allFields = c.getDeclaredFields();
for (int i = 0; i < allFields.length; i++) {
String fieldName = allFields[i].getName();
Class typeClass = allFields[i].getType();
String fieldType = typeClass.getName();
System.out.println("字段名: " + fieldName + ", 类型: " + fieldType);
}
}
⑦ 获取构造方法
构造方法是在创建类对象时调用的特殊方法,构造方法可以重载,由它们的参数加以区别。调用getConstructors方法可以取得类构造方法的有关信息,这个方法返回一个数组的
Constructor对象。可以用 Constructor对象里的相关方法来确定构造方法的名字、描述符、参数类型和抛出的意外列表。也可以用Constructor.newInstance创建一个新的Constructor对象。
//分析类的构造方法
public static void showConstructors(Object o) {
Class c = o.getClass();
Constructor[] theConstructors = c.getConstructors();
for (int i = 0; i < theConstructors.length; i++) {
System.out.print(theConstructors[i].getName());
System.out.print(" ( ");
Class[] parameterTypes = theConstructors[i].getParameterTypes();
for (int k = 0; k < parameterTypes.length; k++) {
String parameterString = parameterTypes[k].getName();
System.out.print(parameterString + " ");
}
System.out.println(")");
}
}
⑧ 获取成员方法
如何找出类的public方法呢?当然是调用getMethods方法。由getMethods方法返回一个数组,数组元素类型是Method对象。方法的名字,类型,参数,描述和抛出的意外都可
以由Method对象的方法来取得。用 Method.invoke 方法自己调用这个方法。
Method类的对象可以通过getName取方法名、getReturnType取返回值的类型、用
getParameterTypes取得参数类型(Class对象)的数组,对每个参数用getName取参数的类型名。
同样,对于非public的方法,可以使用getDeclaredMethods()方法获取。
//分析类中的成员方法
public static void showMethods(Object o) {
Class c = o.getClass();
Method[] theMethods = c.getMethods();
for (int i = 0; i < theMethods.length; i++) {
String methodString = theMethods[i].getName();
System.out.println("Name: " + methodString);
String returnString = theMethods[i].getReturnType().getName();
System.out.println(" Return Type: " + returnString);
Class[] parameterTypes = theMethods[i].getParameterTypes();
System.out.print(" Parameter Types:");
for (int k = 0; k < parameterTypes.length; k++) {
String parameterString = parameterTypes[k].getName();
System.out.print(" " + parameterString);
}
System.out.println();
}
}