反射的作用:
 
1.运行时检查类的结构
2.运行时更改类的字段值
3.调用类的方法
 
准备知识:
 
Class类:虚拟机为每一个对象保存的一份对象所属类的清单:
static Class forName(String className) 获取字符串(接口或者类的全类名)对应的类的Class对象。
Object newInstance() 返回Class对应的类的一个对象
 
解析: 
1.运行时检查类的结构
    java.lang.reflection 中有三个类:
    1.Field 对应类的字段
        getName() 返回Field对应的名称
        getType() 返回Field所在的Class类型
    2.Method 对应类的方法
        getName() 返回Method 对应的名称
        Class<?>[] getParameterTypes() 按方法声明的顺序返回参数类型数组
        int getModifiers() 返回一个整数值,用不同的位开关表示static,public这样的修饰情况。
    3.Constructor 对应构造器
        getName() 返回Constructor 对应的名称
        Class<?>[] getParameterTypes() 按方法声明的顺序返回参数类型数组
        int getModifiers() 返回一个整数值,用不同的位开关表示static,public这样的修饰情况。
 
在Method和Constructor中可以使用Modifier类的isPrivate,isStatic 来判断getModifiers()的返回值,给出是否含有对应的修饰符。
Class对象的getDeclaredConstructors,getDeclaredMethods,getDeclaredFields分别用于获取对象的构造器,方法,字段,以数组的形式返回。
 
下面为反射基本用法:检测一个类的结构:
 
 import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; //反射基本测试
public class ReflectionTest {
public static void main(String[] args) {
String name = "java.util.Date";
try {
Class cl = Class.forName(name);
Class supercl = cl.getSuperclass();
String modifiers = Modifier.toString(cl.getModifiers());
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print("class " + name);
if (supercl != null && supercl != Object.class) System.out.print(" extends "
+ supercl.getName()); System.out.print("\n{\n");
printConstructors(cl);
System.out.println();
printMethods(cl);
System.out.println();
printFields(cl);
System.out.println("}");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.exit(0);
} public static void printConstructors(Class cl) {
Constructor[] constructors = cl.getDeclaredConstructors(); for (Constructor c : constructors) {
String name = c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers());
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print(name + "("); // print parameter types
Class[] paramTypes = c.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
} public static void printMethods(Class cl) {
Method[] methods = cl.getDeclaredMethods(); for (Method m : methods) { Class retType = m.getReturnType();
String name = m.getName(); System.out.print(" ");
// print modifiers, return type and method name
String modifiers = Modifier.toString(m.getModifiers());
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print(retType.getName() + " " + name + "("); // print parameter types
Class[] paramTypes = m.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
} public static void printFields(Class cl) {
Field[] fields = cl.getDeclaredFields(); for (Field f : fields) {
Class type = f.getType();
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.println(type.getName() + " " + name + ";");
}
}
}
2.更改类的字段值:
    Field对象有以下对应的一系列方法:
    public Object get(Object obj) 获取目标对象上字段的值
    public void set(Object obj, Object value)设置目标对象上字段的值
    有相应具体类型的get和set方法。
 
3.调用类的方法(类似于方法指针):
    Method对象方法:
     public Object invoke(Object obj, Object... args)
    obj是调用的目标对象,ars是方法参数
 
以下为示例代码:
 import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; /**
* Created by karlx on 2015/5/29.
*/
public class ReflectionTest2 {
public static void main(String[] args) {
Person person = new Person();
person.name = "karl";
//获取,设置 运行中对象的字段值
Class clazz = person.getClass();
try {
Field field = clazz.getField("name");
field.setAccessible(true);//避开java的访问检查
System.out.println(field.get(person)); field.set(person, "xiaoming");
System.out.println(field.get(person)); } catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
//运行中调用对象的方法
try {
Method method = clazz.getMethod("getName");
method.setAccessible(true);//避开java的访问检查
System.out.println(method.invoke(person));
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
} static class Person {
public String name; public String getName() {
return name + "hello";
} public void setName(String name) {
this.name = name;
}
}
}
05-08 15:51
查看更多