self-confidence,the source of all the power

导航

反射机制

1、反射的作用 

一般情况下,我们想得到一个类的实例只需要直接创建它就好了,如现在有一个类文件Person.class, 创建对象代码如下

Person p = new Person();

现在我们假设一种场景,我们在配置文件中记录下一个类名及它的一个方法名,然后我们将该配置文件读取出来,能否通过里面的字串内容来得到对应的实例并执行方法呢?答案是肯定的,这正是反射存在的原因,它一般出现在框架的搭建。配置文件可以这样写

com.xxx.cn.Person  getName

上面第一个字串是类的全名,第二个为方法名。

2、如何通过反射来执行字串中的方法名呢

介绍反射的文章很多,在最开始的学习中,始终没有真正理会,总是在看了忘忘了看的循环中,原因就在于只知其然不知其所以然,在这我按自己的理解来分解介绍。

现在回到问题原点,怎么将一个表示类名的字串转化成实例并执行它的方法, 我将整个过程分为三部分

    1)根据类名得到类

    2)反射得到类的构造方法并实例化

    3)反射方法并调用

   这样一分,整个反射过程就变得很简单了,不再因为各种各样的反射API而不知所措了。

3、反射API

以ExamNameBean为例来一一说明

public class ExamNameBean implements Serializable {
    private static final long serialVersionUID = 1557158345411694553L;
    public ExamNameBean(int i, String s){
Log.d(TAG, "ExamNameBean: ");
}
private String examName; private long uploadTime; private boolean correct; public String getExamName() { return examName; } public void setExamName(String examName) { this.examName = examName; } public long getUploadTime() { return uploadTime; } public void setUploadTime(long uploadTime) { this.uploadTime = uploadTime; } private boolean isCorrect() { return correct; } private void setCorrect(boolean correct) { this.correct = correct; } }

获取类的方法有三种

        Class<?> class1 = null;
        Class<?> class2 = null;
        Class<?> class3 = null;
        // 三种方式获取
        class1 = Class.forName("com.xxx.packetname.ExamNameBean");
        class2 = new ExamNameBean().getClass();
        class3 = ExamNameBean.class;

接着反射类的构造方法并实例化

Class c = Class.forName("com.xxx.ExamNameBean");
        //取公共的无参构造函数
        Constructor construct = c.getConstructor(null);
        //取有参的构造函数
        Constructor c2 = c.getConstructor(int.class, String.class);
        //实例化对像
        ExamNameBean exam = (ExamNameBean) construct.newInstance();
        ExamNameBean exam2 = (ExamNameBean) c2.newInstance(1,"name");

在得到实例化后的对象,这个时候只要再把方法反射出来就可以调用了

Method m = c.getMethod("getExamName", null);
m.invoke(exam, null); //getExamName()调用,需要指定类实例,表示是调用谁的方法

以上反射的方法及构造函数,都是公共属性的,那怎么访问私有方法呢,正常情况下,我们是没法调用对象的私有方法的,但是在反射时,却可以通过暴力反射去访问类的私有成员,包括私有构造方法,私有变量,私有方法等

Method privateM = c.getDeclaredMethod("test", null);
privateM.setAccessible(true);//暴力反射
privateM.invoke(exam,null);

总结

     反射时,凡涉及到私有属性的成员反射时,其API名字都具有getDeclaredXXX()特点,并需要setAccessible(true)将其暴露出来,如果是公共成员的反射API名都不带Declared字样。

 获取构造方法
    getConstructors
    getDeclaredConstructors
 · 获取所有成员
    getFields
           getDeclaredFields
        · 获取单个成员
    getField
    getDeclaredField
        · 修改成员的值
    set(Object obj,Object value) :将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
 · 获取所有方法
    getMethods
    getDeclaredMethods
        · 获取单个方法
    getMethod
    getDeclaredMethod
        · 暴力访问
    method.setAccessible(true);

 

    

 

 

 

 

 

 

   

posted on 2017-06-30 15:32  漩涡鸣人  阅读(158)  评论(0编辑  收藏  举报