Java 反射简介

何为反射?


反射是一种动态获取运行状态的类的信息(属性和方法等)的能力。

简单说,对于Java中任何一个类,我们都可以获取它的属性和方法。


如何实现反射?


了解它之前,我们首先需要了解Java中的Class类。

http://blog.csdn.net/hyhyl1990/article/details/49227301  (Java Class类简介)


对于每一个类,初始化时Java虚拟机都会对它生成字节码(.class),我们可以通过Class类来实现动态获取和调用类的属性和方法。


通过反射调用类的方法.


使用反射调用类的方法主要是通过java.lang.reflect.Method类来实现的。

Method类提供了类或者接口的某个方法的信息(方法明,修饰符,参数等等)。既包括类的静态方法也包括实例方法(对象方法)。


获取到一个Method对象(它对应一个类的方法)后,我们可以调用method对象的invoke函数来实现对该方法的调用。


public Object invoke(Object obj, Object... args)


obj参数是调用该方法的类对象(如果是静态方法,不需要实例化类对象),args是给该方法传递的参数信息。


Demo:

我们自定义一个类MyClass2,它有如下的几种方法,我们通过反射机制逐一调用。

public class MyClass2 {
	
	static int staticVal;
	int val;
	
	public MyClass2() {}
	
	public MyClass2 (int val) {
		this.val = val;
	}
	
	public static void staticShowVal() {
		System.out.println("MyClass2 fun. static showVal null param");
		System.out.println(staticVal);
	}
	
	public void showVal() {
		System.out.println("MyClass2 fun. showVal null param");
		System.out.println(this.val);
	}
	
	public void showVal(int  val) {
		System.out.println("MyClass2 fun. showVal String param");
		System.out.println(val + "");
	}
	
	public void showVal(String[] vals, int[] intVals) {
		System.out.println("MyClass2 fun. showVal String[] param & int[] param");
		for (int i = 0; i < vals.length; i++) {
			System.out.println(vals[i]);
		}
		for (int i = 0; i < intVals.length; i++) {
			System.out.println(intVals[i]);
		}
	}
	
}

以下是使用反射进行不同的方法调用。

在使用反射进行调用之前,我们需要先获取该类的Class对象,一般可以由以下方法获得:

Class<?> class2 = null;
try {
	class2 = Class.forName("com.hyl.MyClass2");
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}


1.调用MyClass2的静态方法

//invoke the static method
Method staticMethod = null;
try {
	staticMethod = class2.getMethod("staticShowVal", null);
	staticMethod.invoke(class2, null);
} catch (Exception e) {
	e.printStackTrace();
}

因为是类的静态方法,所以invoke的第一个参数,我们并不需要初始化一个MyClass2的实例,直接使用我们上面得到的MyClass2类的Class对象即可。

因为要调用的方法是无参数的,所以invoke的第二个参数我们传递null即可。


2.调用MyClass2的成员方法(空参数)

Method method = null;
try {
	method = class2.getMethod("showVal", null);
	Object obj1 = class2.newInstance();
	method.invoke(obj1, null);
 } catch(Exception e) {
	e.printStackTrace();
}

与调用静态方法不同,调用成员方法,我们需要首先初始化该方法所属类的一个实例,使用类的class对象的newInstance()方法即可得到一个实例化。


3.调用MyClass2的含int参数的成员方法

Method method = null;
try {
        method = class2.getMethod("showVal", new Class<?>[] {int.class});
	//MyClass2 must have an default null params Constructor
	Object obj1 = class2.newInstance();
	nt v = 3;
	method.invoke(obj1, new Object[]{v});
} catch(Exception e) {
	e.printStackTrace();
}

与调用空参数的方法不同,要调用带参数的成员方法,我们需要:

使用getMethod方法得到Method对象时,要传入相应的参数类型(Class数组)

使用invoke调用时也要传递相应的参数。


之前在讲解Class类时,我们有提到,每个基本数据类型也都对应有自己的Class类型。int类型对应的Class类型即是int.class.


4.调用MyClass2的含String数组int数组参数的成员方法

try {
	method = class2.getMethod("showVal", new Class<?>[] {String[].class, int[].class});
	Object obj1 = class2.newInstance();
	String[] strArr = {"1", "2"};
	int[] intArr = {1, 2};
	method.invoke(obj1, new Object[]{strArr, intArr});
} catch (Exception e) {
	e.printStackTrace();
}

和上面的调用基本相同,只是需要根据要调用方法的参数类型传递相应的参数。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值