飘飞的海

 

反射机制

一、定义

JAVA反射机制是在运行状态中:1)对于任意一个类,都能够知道这个类的所有属性和方法;2)对于任意一个对象,都能够调用它的任意一个方法。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二、提供的功能:

1) 在运行时判断任意一个对象所属的类;

2)在运行时构造任意一个类的对象;

3)在运行时判断任意一个类所具有的成员变量和方法;

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

5)生成动态代理。

三、使用的原因

1、扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。

2、在编码阶段不知道那个类名,要在运行期从配置文件读取类名,这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。

四、应用举例

示例中用到的类

class Cat {
    /*
     * 用于测试反射机制,省略了参数的getter和setter类
     */
    private String name;
    private int age;
    private String sex;
    public String hostname;//主人名字
    public static String info="猫是一种XX的动物……";//动物说明
    public Cat(){
        this.name="defaultname";
        this.age=0;
        this.sex="defaultSex";
        this.hostname="Lucy";
    }
    public Cat(String name,Integer age,String sex) {
        this.name=name;
        this.age=age;
        this.sex=sex;
        this.hostname="Kate";
    }
    public static void showCatInfo(String time){
        System.out.println("Cat.showCatInfo():"+info);
    }
    public void feed(String host){
        System.out.println("Cat.feed()"+host);
    }
}

 

1、获取某个对象的属性

    public Object getProperty(Object owner,String fieldName) throws Exception {
        Class ownerClass=owner.getClass();//通过已知对象获取其Class对象
        Field field=ownerClass.getField(fieldName);//通过Class对象获取声明的属性
        Object property=field.get(owner);//通过对象获取属性的实例,如果该属性是私有的会异常
        return property;
    }

使用如下代码测试该方法:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Reflector rf=new Reflector();
        Cat cat=new Cat();
        try {
            Object object=rf.getProperty(cat, "hostname");
            if(object!=null){
                System.out.println("Reflector.main()"+object.toString());                
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

输出:Reflector.main()Lucy

2、获取某个类的静态属性

    public Object getStaticProperty(String className,String fieldName) throws Exception {
        Class ownerClass=Class.forName(className);//获取已知对象的Class对象
        Field field=ownerClass.getField(fieldName);//通过Class对象获取声明的属性
        Object property=field.get(ownerClass);//因为该属性是静态属性,应该从类Class里直接获取,此处是ownerClass
        return property;
    }

 

测试代码:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Reflector rf=new Reflector();
        try {
            Object object=rf.getStaticProperty("com.Cat", "info");
            if(object!=null){
                System.out.println("Reflector.main()"+object.toString());                
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

输出:Reflector.main()猫是一种XX的动物……

3、执行某对象的方法

    public Object invokeMethod(Object owner,String methodName,Object args[]) throws Exception{
        Class ownerClass=owner.getClass();//获取已知对象的Class对象
        Class[] argClasses=new Class[args.length];//获取参数对象的Class
        for(int i=0;i<args.length;++i){
            argClasses[i]=args[i].getClass();
        }
        Method method=ownerClass.getMethod(methodName, argClasses);//通过方法名和参数对象的Class获取方法对象
        return method.invoke(owner, args);//通过执行这个方法的对象和参数对象数组执行这个方法,返回值是Object,也既是该方法的返回值。
    }

测试代码:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Reflector rf=new Reflector();
        Cat cat=new Cat();//执行方法的对象 
        Object arg[]={(Object)new String("Mary")};//方法的参数对象数组
        try {
            rf.invokeMethod(cat, "feed",arg);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

输出:Cat.feed()Mary

4、执行某个类的静态方法

    public Object invokeStaticMethod(String className,String methodName,Object args[]) throws Exception{
        Class ownerClass=Class.forName(className);//获取已知对象的Class对象
        Class[] argClasses=new Class[args.length];//获取参数对象的Class
        for(int i=0;i<args.length;++i){
            argClasses[i]=args[i].getClass();
        }
        Method method=ownerClass.getMethod(methodName, argClasses);//通过方法名和参数对象的Class获取方法对象
        return method.invoke(null, args);//通过执行这个方法的对象和参数对象数组执行这个方法,返回值是Object,也既是该方法的返回值。
    }

测试代码:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Reflector rf=new Reflector();
        Object arg[]={(Object)new String("Mary")};//方法的参数对象数组
        try {
            rf.invokeStaticMethod("com.Cat", "showCatInfo",arg);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
//PS:基本的原理和例3相同,不同点是最后一行,invoke的一个参数是null,因为这是静态方法,不需要借助实例运行。

输出:Cat.showCatInfo():猫是一种XX的动物……

5、新建实例

    /*
     * 新建实例
     * 这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。
     */
    public Object newInstance(String className,Object args[])throws Exception{
        Class ownerClass=Class.forName(className);//获取已知对象的Class对象
        Class[] argClasses=new Class[args.length];//获取参数对象的Class
        for(int i=0;i<args.length;++i){
            argClasses[i]=args[i].getClass();
        }
        Constructor constructor=ownerClass.getConstructor(argClasses);//获取这个类的构造器
        return constructor.newInstance(args);//新建实例
    }

测试代码:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Reflector rf=new Reflector();
        Object arg[]=new Object[3];//方法的参数对象数组
        arg[0]=new String("CatName1");
        arg[1]=new Integer(3);
        arg[2]=new String("Male");
        try {
            Cat cat=(Cat)rf.newInstance("com.Cat",arg);
            System.out.println("Cat name is "+cat.getName());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

输出:Cat name is CatName1

posted on 2012-09-24 17:51  飘飞的海  阅读(153)  评论(0编辑  收藏  举报

导航