Java反射机制生成实例

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

posted @ 2013-01-29 19:45  IamThat  阅读(780)  评论(0编辑  收藏  举报