Java的反射机制

来源:互联网 发布:工作便签软件 编辑:程序博客网 时间:2024/06/04 19:16

今年暑期项目实训中我接到的任务是做整个项目的菜单界面。其中要利用到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;}}


下面的是MyReflection02类,以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();}}

 

1 0
原创粉丝点击