您的位置:首页 > 编程语言 > Java开发

反射机制

2016-04-25 10:52 603 查看
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

痛苦的反射机制,贴上代码和注释,一遍看代码一边学习

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Reflection {

/**
* 得到某个对象的公共属性
* @param owner, fieldName
* @return 该属性对象
* @throws Exception
*
*/
public Object getProperty(Object owner, String fieldName) throws Exception {
Class ownerClass = owner.getClass(); // 通过Object类的getClass()方法获取Class对象
Field field = ownerClass.getField(fieldName); // 返回Field对象 反映此Class对象所表示的类或接口的指定公共成员字段
Object property = field.get(owner); // 拿到对象实例的域成员的值
return property;
}

/**
* 得到某类的静态公共属性
* @param className   类名
* @param fieldName   属性名
* @return 该属性对象
* @throws Exception
*/
public Object getStaticProperty(String className, String fieldName) throws Exception {
Class ownerClass = Class.forName(className); //通过Class类的静态方法来获取Class对象
Field field = ownerClass.getField(fieldName); //
Object property = field.get(ownerClass);
return property;
}

/**
* 执行某对象方法
* @param owner      对象
* @param methodName    方法名
* @param args   参数
* @return 方法返回值
* @throws Exception
*/
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
Class ownerClass = owner.getClass();
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
// 第一个参数是方法名,第二个参数是该方法的参数类型
// 因为存在同方法名不同参数这种情况,所以只有同时指定方法名和参数类型才能唯一确定一个方法
// 第一个参数是具体调用该方法的对象 第二个参数是执行该方法的具体参数
// 如一个函数 int Test(int a, String str);
// 对应的getMethod方法:
// 1.  getMethod("Test",int.class,String.class);
// 2. getMethod("Test",new Class[]{int.class,String.class});
Method method = ownerClass.getMethod(methodName, argsClass);
// 然后通过invoke来调用此方法:
// 函数原型:Object Java.lang.reflect.Method.invoke(Object receiver, Object... args)
// Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,
// 如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,
// 如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回
// receiver:该方法所在类的一个对象
// args: 传入的参数 如 100,“hello”
return method.invoke(owner, args);
}

/**
* 执行某类的静态方法
* @param className       类名
* @param methodName      方法名
* @param args            参数数组
* @return 执行方法返回的结果
* @throws Exception
*/
public Object invokeStaticMethod(String className, String methodName, Object[] args) throws Exception {
Class ownerClass = Class.forName(className); //通过Class类的静态方法来获取Class对象
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Method method = ownerClass.getMethod(methodName, argsClass);
return method.invoke(null, args);
}

/**
* 新建实例
*
* @param className
*            类名
* @param args
*            构造函数的参数
* @return 新建的实例
* @throws Exception
*/
public Object newInstance(String className, Object[] args) throws Exception {
Class newoneClass = Class.forName(className);
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
// 返回一个Constructor对象,它反映此Class对象所表示的类的指定公共构造。
// 参数是一个数组的Class对象识别的构造函数的形参类型,在声明的顺序。
// 例如: Constructor c = String.class.getConstructor( new Class[]{ String.class } );
Constructor cons = newoneClass.getConstructor(argsClass);
// Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数; 要求被调用的构造函数是可见的,也即必须是public类型的;
// Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数;在特定的情况下,可以调用私有的构造函数。
return cons.newInstance(args);

}

/**
* 是不是某个类的实例
* @param obj 实例
* @param cls 类
* @return 如果 obj 是此类的实例,则返回 true
*/
public boolean isInstance(Object obj, Class cls) {
// 确定指定的对象是与这个类表示的对象赋值兼容的,如果是返回true
return cls.isInstance(obj);
}

/**
* 得到数组中的某个元素
* @param array 数组
* @param index 索引
* @return 返回指定数组对象中索引组件的值
*/
public Object getByArray(Object array, int index) {
return Array.get(array, index);
}
}


java的反射机制就是增加程序的灵活性,避免将程序写死到代码里

例如: 实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。

            使用反射: class.forName("person").newInstance(); 而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息