Java中的反射机制

1)概念:
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2)功能:
  1>在运行时判断任意一个对象所属的类;
  2>在运行时构造任意一个类的对象;
  3>在运行时判断任意一个类所具有的成员变量和方法;
  4>在运行时调用任意一个对象的方法;
  5>生成动态代理。

3)获得某个对象的具体属性:
  Class ownerClass = owner.getClass():得到对象owner的Class。
  Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。
  Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。如果需要访问到对象的private属性,需要首先调用:AccesibleObject.setAccessible(Field名字,true);
  如果说是获取Class的静态属性:则第三句换成Object property=field.get(Class名字),而不是用实例的名字。

4)执行某个对象的方法:

  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 = args.getClass();
    }
    Method method = ownerClass.getMethod(methodName, argsClass);
    return method.invoke(owner, args);
  }
  如果是执行某个类的静态方法:method.invoke(null, args);

5)新建某对象的实例:
  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 = args.getClass();
    }
    Constructor cons = newoneClass.getConstructor(argsClass);
    return cons.newInstance(args);
  }
  这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。

6)判断是否为某个class的实例:
  public boolean isInstance(Object obj, Class cls) {
    return cls.isInstance(obj);
  }

7)Reflection与introspection
  Reflection这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods1。

  这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

  以上部分参考:http://pengcqu.iteye.com/blog/486575

  下面部分纯粹自己做练习。


结合例子讲解:

  Class Demo implements interfaceOne, interfaceTwo{
    private int age;
    public Demo(){}
    public Demo(String str){}
    public Demo(String str, int x){}
    public void testMethod(){...}
    public void setAge(int age){...}
    public int getAge(){...}
  }

通过一个对象获得完整的包名和类名

  Demo demo = new Demo();
  demo.getClass().getName(); //包名+类型 etc:reflect.Demo


实例化Class类对象:推荐使用第一种

	//第一种:通过Class.forName("包名+类名")
	Class<?> demo1 = Class.forName("reflect.Demo");
	//第二种:
	Class<?> demo2 = new Demo().getClass();
	//第三种:
	Class<?> demo3 = Demo.class;

通过Class实例化其他类的对象

	Class<?> dmeo = Class.forName("reflect.Demo");
	Demo instance = demo.newInstance();

  注意:通过Class.newInstance()时,前提是Demo类必须有无参构造函数,因为newInstance()会默认调用无参构造方法

 

通过Class调用其他类中的构造函数 

	Class<?> demo = Class.forName("reflect.Demo");
	// 获得Demo.Class的所有构造方法
	Constructor<?> cons[]=demo.getConstructors();
	* 数组的顺序跟构造函数声明的顺序相反
	* cons[0] : Demo(String, int)
	* cons[1] : Demo(String)
	* cons[2] : Demo() 
	Demo instance = null;
	instance = (Demo) cons[0].newInstance("hello", 20);
	instance = (Demo) cons[1].newInstance("hello");
	instance = (Demo) cons[2].newInstance();<span style="font-family: 'Microsoft YaHei';font-size:12px; background-color: rgb(255, 255, 255);"> </span>


返回一个类实现的接口、继承的父类

	Class<?> demo = Class.forName("reflect.Demo");
	Class<?> [] interfaces = demo.getInterfaces();
	// 获得指定下标的接口名
	String interfaceName = interfaces[i].getName();
	// 获得父类的名字
	Class<?> superClass = demo.getSuperclass();
	String superClassName = superClass.getName();

 

获取修饰符

	Class<?> demo = Class.forName("reflect.Demo");
	// 获得所有的构造方法
	Constructor<?> cons[] = demo.getConstructors();
	for (int i = 0; i < cons.length; i++) {
		// 获得修饰符的值
		int mod = cons[i].getModifiers();
		// 将修饰符的值转变为String类型(etc: public, private....)
		String modifier = Modifier.toString(mod);
		// 获得参数类型
		Class<?> paramTypes[] = cons[i].getParameterTypes();
		for (int j = 0; j < paramTypes.length; j++) {
			// 获得参数名
			String paramName = paramTypes[j].getName();
		}
	}

 

获得类的所有方法

	Class<?> demo = Class.forName("reflect.Demo");
	Method[] methods = demo.getMethods();
	for (int i = 0; i < methods.length; i++) {
		// 获取修饰符
		int mod = methods[i].getModifiers();
		String modifier = Modifier.toString(mod);
		// 获取返回值
		Class<?> returnType = methods[i].getReturnType();
		String returnTypeName = returnType.getName();
		// 获取方法名
		String methodName = methods[i].getName();
		// 获取方法参数
		Class<?> paramTypes[] = methods[i].getParameterTypes();
		for (int j=0; j<paramTypes.length; j++){
			String paramName = paramTypes[j].getName();
		}
	}
 

取得其他类的全部属性

	Class<?> demo = Class.forName("reflect.Demo");
	// 取得本类的全部属性
	Field[] fields = demo.getDeclaredFields();
	for (int i=0; i<fields.length; i++) {
		// 获取修饰符
		String modifier = Modifier.toString(fields[i].getModifiers());
		// 获取类型
		Class<?> type = fields[i].getType();
		String typeName = type.getName();
		// 获取属性名
		String paramName = fields[i].getName();
	}

 

取得实现的接口或者父类的属性

	Field[] fieldParam = demo.getFields();
	for (int i=0; i<fieldParam.length; i++) {
		// 获取修饰符
		String modifier = Modifier.toString(fieldParam[i].getModifiers());
		// 获取类型
		Class<?> type = fieldParam[i].getType();
		String typeName = type.getName();
		// 获取属性名
		String paramName = fieldParam[i].getName();
	}

 

通过反射调用其他类中的方法

	Class<?> demo = Class.forName("reflect.Demo");
	Method method = demo.getMethod("testMethod");
	// 调用Demo中的testMethod方法
	method.invoke(demo.newInstance());


调用其他类的set和get方法

	Class<?> demo = Class.forName("reflect.Demo");
	Object instance = demo.newInstance();
	Method setter = demo.getMethod("setAge", int.class);
	setter.invoke(instance, 20);
	Method getter = demo.getMethod("getAge");
	int age = (Integer) getter.invoke(instance);

 

通过反射操作属性

	Class<?> demo = Class.forName("reflect.Demo");
	Object instance = demo.newInstance();
	Field field = demo.getDeclaredField("age");
	// 如果字段是私有的,那么必须要对这个字段设置 field.setAccessible(true) 这样才可以正常使用
	field.setAccessible(true);
	// 设置属性值
	field.set(instance, 30);
	// 获得属性值
	int age = field.getInt(instance);
 

取得并修改数组的信息

	int[] temp={1,2,3,4,5};
	Class<?> demo=temp.getClass().getComponentType();
	数组类型:demo.getName();
	数组长度:Array.getLength(temp);
	数组的第一个元素:Array.get(temp, 0);
	设置第一个元素的值为100:Array.set(temp, 0, 100);



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值