Java的反射机制

今年暑期项目实训中我接到的任务是做整个项目的菜单界面。其中要利用到java中的反射机制,所以学习下这一个知识点。

实训任务要求:窗口中显示管理信息系统的功能菜单项,当用户要点击某个功能菜单项时,能够出现该功能相应的界面。

根据要求,或许有诸多解决方案,例如识别出用户点击哪个菜单项,然后再创建相应的类的对象,调用相应的方法,但是这种方案或编程复杂或代码垄杂,建议不要使用。最好的解决方案莫过于利用java的反射机制,动态的调用各个模块的类。

1、   什么是Java的反射机制?

Java反射机制是指程序在运行状态中,动态获取类中的所有信息以及动态调用对象方法的功能。

2、   java反射机制的原理是什么?

想要知道反射原理,我们就必须先来看java程序的执过程。想要java程序能够运行,java类必须被java虚拟机加载。运行程序都是在编译时就已经加载了所需要的类。我们在这先讲一下什么是编译:编译就是编辑器帮你把代码翻译成电脑可以识别的代码,编译器在编译时会做一些简单的工作,例如检查你的语法是否有误,关键字是否有错等,还有加载类。当你用eclipse(或其他高级编辑器)写好一个类时,你的程序其实已经做完了编译的功能。如果你用记事本写一个类,在Dos命令行下执行javac 类名.java时,就是在编译。编译好了后,那么程序就到运行了,运行时你的代码被装载到内存中,运行时的检查就是在你的内存中做操作与判断,下面举个例子:

int  sun[] = new int[6];

sun[6] = 8;

上面的代码明显的是数组下标越界的错误,但是程序在编译时是不会出错的,在运行时却会出现错误的,报出ArrayIndexOutOfBountsException的异常,这个就是程序编译和运行时的区别。

    但是java的反射机制在编译时是不能确定哪个类被加载进来了(和我上面任务要求一样,你现在编写的程序怎么能知道将来用户会点哪个菜单项,加载哪个类?),它是在程序运行的时候才加载和使用的(所以要用java的反射机制)。

3、   通过java的反射我们可以实现什么功能?

1、   在运行时判断任意一对象所属类。

2、   在运行时构造任意一个类的对象。

3、   在运行时,判断任意一个类所具有的属性和方法。

4、   在运行时调用任意一个对象的方法。

4、  java的反射常用的类

1、   Class类:java中反射的核心类,通过Class类可以获得类的属性,方法等内容。Class class = Class.forName(“类名”),加载类有多种方法,在这就用Class.forName()的方法吧!注意:类名必须是全名,也 就是 要有包名,如果你创建工程时建了包就加上,格式为:包名.类名,未加包就直接是类名称 即可

2、   Filed类:表示类中的属性,可获得和更改类中属性的值。

Field   field = class.getField(String name)//根据属性名,得到相应的属性。

Field[ ]  field = class.getFields()//获得类中所有的public属性。

Field[ ]  field = class.getDeclaredFields()//得到类中public和非public的属性。

Field  field = class.getDeclareField(String name)//根据属性名,得到对应的public和非public的属性。

3、   Method类:表示类的方法,可以用来获取类中方法的信息和执行方法。

Method method =class.getDeclaredMethod(String name, Class[ ] params)//根据方法名和参数,得到指定的 public和非public的方法。

Method[ ] method =class.getDeclareMethods()//得到所有的public和非public的方法。

Method method =class.getMethod(String name, Class[ ] params)//根据方法名和参数,得到指定的公共方法。

Method[ ] method =class.getMetnods()//得到所有的public的方法。

4、   Constructor类:表示类的构造方法。

Constructor  constructor =class. getDeclareConstructor(Class[ ] params)//根据参数,得到指定的构造方法。

Constructor[ ] constructor=class. getDeclareConstructors()//得到所有的构造方法。

Constructor constructor= class.getConstructor(Class[ ] parame)//得到指定的带参数的公共构造方法。

Constructor[ ] constructor= class.getConstructors()//得到类中所有公共构造方法。

以上方法是一些基本的方法,更多方法的使用请查阅API手册Class类。相信读者已经对java的反射有一定的了解了,那么就用代码来实现一下吧!

下面是myReflection01类:

package Reflection;

public class myReflection01 
{
	private int age;
	private String  string= "hello!";
	public boolean is = true;
	
	//构造方法
	public myReflection01() 
	{
		this.age = 10;
		System.out.println("hello!");
	}
	
	//公共Out方法
	public void  Out()
	{
		System.out.println("age:" + age);
	}
	
	//公共name方法
	public int name(int n) 
	{
		n += 2;
		return n;
	} 
	
	//私有say方法
	private void say()
	{
		System.out.println("这个是一个私有的方法,你可以得到吗?");
	}
	 
	//私有成员的取得和设置
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getString() {
		return string;
	}

	public void setString(String string) {
		this.string = string;
	}


}


下面的是M yReflection02类,以myReflection做测试。
package Reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.jar.Attributes.Name;

public class MyReflection02 
{
	public Object getProperty(String classname ) throws NoSuchMethodException, IllegalArgumentException, InvocationTargetException 
	{
		try 
		{
			Class  class1  = Class.forName(classname);
			//创建一个classname类的对象,并调用它的无参数构造方法。
			Object  property = class1.newInstance();
		
			System.out.println("property的类名是:" +property.getClass());
			System.out.println(class1.getName());
			
			System.out.println("得到构造函数");
			//获得构造函数的方法 返回的是一个数组
			Constructor[]  constructors = class1.getConstructors();
			for (int i = 0; i < constructors.length; i++)
				System.out.println(constructors[i]);
			
			System.out.println("得到方法");
			//得到公共方法
			Method[] methods = class1.getMethods();
			for (int i = 0; i < methods.length; i++)
				System.out.println(methods[i]);
			
			System.out.println("得到公共成员的属性");
			//得到类中的属性, 私有的不能获得
			Field[] fields = class1.getFields();
			for (int i = 0; i < fields.length; i++) 
				System.out.println(fields[i]);
			
			try 
			{//获取私有属性的值 	获取myReflection01类中age,string这个私有属性
				Field f1 = class1.getDeclaredField("string");
				Field f2 = class1.getDeclaredField("age");
				//要先设置允许访问
				f1.setAccessible(true);
				f2.setAccessible(true);
				//通过get方法来获得该属性的值			//参数为一个myReflection01的对象
				String  getString = (String) f1.get(property);
				 int   getage  =   (int) f2.get(property); 
				System.out.println("得到该类的石油成员age的值是:" +getage);
				System.out.println("得到该类的私有成员值是:"+getString);
				
			} catch (NoSuchFieldException e) 
			{
				e.printStackTrace();
			} catch (SecurityException e) 
			{
				e.printStackTrace();
			}
			
			//得到所有的公共构造方法
			System.out.println("公共构造方法");
			Constructor[]  constructor = class1.getConstructors();
			for (int i = 0; i < constructor.length; i++) 
				System.out.println(constructor[i]);
			//通过反射调用方法
			try 
			{
				//在这执行了invokeMethod方法,请看该方法
				//参数分别为myReflection01的实例, myReflection01中的name方法名, name中传入的参数
				int  res = (int) invokeMethod(property, "name", new  Object[] {1});
				
			} catch (SecurityException e) 
			{
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) 
		{
			e.printStackTrace();
		} catch (InstantiationException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		return classname;	
	}
	
	private Object invokeMethod(Object owner, String methodName, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
	{
		Class  ownerClass  = owner.getClass();
		Class[] argsClass = new Class[args.length];
		for (int i = 0; i < args.length; i++) 
			argsClass[i] = args[i].getClass();//获得方法中每个参数的类型
		
		Method method = null;
		try {
			//得到和methodName名称相同。参数为argsClass一致的方法
			method = ownerClass.getDeclaredMethod(methodName,  argsClass);
			
		} catch (NoSuchMethodException e1) {
			e1.printStackTrace();
		} catch (SecurityException e1) {
			e1.printStackTrace();
		}
		
		//执行该方法,第一个参数为之前myReflection01类的对象, 第二个参数为实际传入的参数
		Object   object = method.invoke(owner, args);
		return object;
	}
	
	public 	MyReflection02() throws IllegalArgumentException, InvocationTargetException
	{
		try {
			//传入类名,这里是加了包的,所以是包名.类名
			getProperty("Reflection.myReflection01");
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
	}
	
	public static void main (String[] args) throws IllegalArgumentException, InvocationTargetException
	{
		new MyReflection02();
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值