http://hi.baidu.com/wuming3632171/item/49834a269bf59b3794f62bc4
看了一下Java OOP的项目,在创建门禁卡登录类别时可以用工厂模式来实现;但后来又考虑了一下在应用工厂模式的同时可以应用Java的反射机制,Java反射的概念我 个人认为很不好理解,通过例子才能融会贯通;其实理解Java的反射和理解JavaScript的eval函数一样,都是将一个字符型数据转换为相应的 类、属性和方法;通过下面的例子来熟悉一下Java的反射;
首先定义一个教员类,如下://教员类public class AccpTeacher { private String name;private int age;public AccpTeacher() { name = "无名氏";age = 22;}public AccpTeacher(String name) { this.name = name;this.age = 22;}public String toString() { return "名字是:" + name;}public String toString(int age, String name) { this.name = name;this.age = age;return "名字是:" + name + ";年龄是:" + age;}}如果我们实例化这个类可以用我们常用的如下方式:public static void main(String[] args){ AccpTeacher accpTeacher = new AccpTeacher();System.out.println(accpTeacher);}可以清晰的想到运行结果是:名字是:无名氏以上是我们最常用的方式,但有时我们想通过字符串来实例化一个类如何做呢,看下面代码:public static void main(String[] args){ // 实例化一个类Object accpTeacher = Class.forName(AccpTeacher.class.getName()).newInstance();System.out.println(accpTeacher);}运行结果同样是:名字是:无名氏首先Class.forName(类名)是将这个类加载到JVM虚拟机中,获得一个类型为Class的类,然后调用其newInstance()方法,相当于实例化(调用无参的构造函数);所以以上两段代码的运行效果是一致的。我们看到AccpTeacher这个类有一个带参数的构造方法,那如何通过反射来调用它呢?看下面代码:public static void main(String[] args){ // 通过构造方法实例化一个类;本例是一个有参数的构造函数,并且构造函数可以为private修饰Class[] argtype = new Class[] { String.class };//代表构造方法的参数类型数组Object[] argparam = new Object[] { "张三" };//代表构造方法的参数值数组Class classType = Class.forName(AccpTeacher.class.getName());Constructor constructor = classType.getDeclaredConstructor(argtype); //获得构造方法,argtype是参数类型数组,我们这里代表的是参数只有一个String类型constructor.setAccessible(true);// 访问私有构造函数,Spring可以配置私有的属性和方法,其实就是用到的这里Object accpTeacher2 = constructor.newInstance(argparam);System.out.println(accpTeacher2);}以上代码的运行结果是:名字是:张三在把教员类放在这里,如下://教员类public class AccpTeacher { private String name;private int age;public AccpTeacher() { name = "无名氏";age = 22;}public AccpTeacher(String name) { this.name = name;this.age = 22;}public String toString() { return "名字是:" + name;}public String toString(int age, String name) { this.name = name;this.age = age;return "名字是:" + name + ";年龄是:" + age;}}下面我想修改类中的属性,看代码:public static void main(String[] args){ // 访问类中的属性,属性可以是private修饰的AccpTeacher accpTeacher3 = (AccpTeacher) Class.forName(AccpTeacher.class.getName()).newInstance();//实例化一个对象Field field = AccpTeacher.class.getDeclaredField("name");//声明一个属性对象,针对这个例子我们操作的这个属性是AccpTeacher类中的name属性field.setAccessible(true);// 私有成员变量System.out.println(field.get(accpTeacher3));//通过实例化的对象调用}以上代码的运行结果是:无名氏再看一下修改属性:接上例public static void main(String[] args){ // 修改类中的属性,属性可以是private修饰的// 接上例field.set(accpTeacher3, "李四");//属性类通过set方法设置属性的值System.out.println(field.get(accpTeacher3));}以上代码的运行结果是:李四最后我们看一下通过反射调用方法:public static void main(String[] args){ // 调用类中的方法(无参),方法可以是private修饰的AccpTeacher accpTeacher4 = (AccpTeacher) Class.forName(AccpTeacher.class.getName()).newInstance();//实例化一个对象Method method = AccpTeacher.class.getMethod("toString", null);//首先声明一个方法类,并通过getMethod()方法获得相应的方法,这个方法中有两个参数,第一个是方法名称的字符串,第二个是方法 中参数类型的数组,这里获得的是AccpTeacher中的toString方法System.out.println(method.invoke(accpTeacher4, new Object[0]));//再看一下方法类中的invoke()这个方法,方法中有两个参数,第一个参数为这个方法的实例对象,第二个参数为方法参数的值的数组}以上代码的运行结果是:名字是:无名氏在看带参的方法:public static void main(String[] args){ // 调用类中的方法(有参),方法可以是private修饰的AccpTeacher accpTeacher5 = (AccpTeacher) Class.forName(AccpTeacher.class.getName()).newInstance();Class[] clazz = new Class[2];//声明类型的数组,AccpTeacher中有一个toString(int,String)的方法clazz[0] = int.class;clazz[1] = String.class;Method method2 = AccpTeacher.class.getMethod("toString", clazz);//获得带参数的方法Object[] obj = new Object[2];//参数值的数组obj[0] = 20;obj[1] = "王五";System.out.println(method2.invoke(accpTeacher5, obj));}以上代码的运行结果是:名字是:王五;年龄是:20
以下是我个人分析学习代码:
Teacher类
package test;
public class Teacher { private String name; private int age; public Teacher() { name = "无名氏"; age = 22; } public Teacher(String name) { this.name = name; this.age = 22; } public String toString() { return "名字是:" + name; } public String toString(int age, String name) { this.name = name; this.age = age; return "名字是:" + name + ";年龄是:" + age; }}package test;
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Test { public static void main(String[] args) throws Exception { Class[] paramenterTypes=new Class[]{String.class};//参数类型 Object[] obj=new Object[]{"张三"};//参数值 Class type=Class.forName(Teacher.class.getName());//通过Class.forName()来加载类,得到这个类类型 Constructor constructor=type.getDeclaredConstructor(paramenterTypes);//由这个类类型以及它的参数得到构造器 constructor.setAccessible(true);//访问私有构造函数,Spring可以配置私有的属性和方法,其实就是用到的这里 Object o=constructor.newInstance(obj); System.out.println(o); Teacher t=(Teacher)Class.forName(Teacher.class.getName()).newInstance(); Field field=Teacher.class.getDeclaredField("name"); field.setAccessible(true); System.out.println(field.get(t)); field.set(t, "李四"); System.out.println(field.get(t)); Teacher t2=(Teacher)Class.forName(Teacher.class.getName()).newInstance(); Method method=Teacher.class.getMethod("toString", null); System.out.println(method.invoke(t2, new Object[0])); Teacher t3=(Teacher)Class.forName(Teacher.class.getName()).newInstance(); Class[] clazz=new Class[2]; clazz[0]=int.class; clazz[1]=String.class; Method method2=Teacher.class.getDeclaredMethod("toString", clazz); Object[] objs=new Object[2]; objs[0]=20; objs[1]="王五"; System.out.println(method2.invoke(t3, objs)); }}输出结果:
名字是:张三
无名氏李四名字是:无名氏名字是:王五;年龄是:20