zoukankan      html  css  js  c++  java
  • 反射机制

    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);

        

       

  • 相关阅读:
    C++11并发内存模型学习
    C++0x对局部静态初始化作出了线程安全的要求,singleton的写法可以回归到最原始的方式
    两次fopen不同的文件返回相同的FILE* 地址
    linux kernel kill jvm
    打印Exception信息
    java map value 排序
    java was started but returned exit code 1
    hive 建表语句
    hadoop mapreduce lzo
    分词 正文提取 java
  • 原文地址:https://www.cnblogs.com/lovemo1314/p/7099095.html
Copyright © 2011-2022 走看看