zoukankan      html  css  js  c++  java
  • 反射

    一、反射的原理

    1、反射的应用  

      类是经过封装的! 不能直接访问类中所有内容!反射是用于打破封装的!可以直接访问到类中的所有内容

      应用在一些通用型比较高的代码中,框架大多数都是使用反射来实现的。

      在框架开发中,都是基于配置文件开发

       **在配置文件中配置了类,可以通过反射得到类中的,所有内容,可以让类中的某个方法执行

      类中的所有内容:属性、没有参数的构造方法,有参数的构造方法、普通方法

    2、反射的原理:

    ①把Java文件保存到本地硬盘(.java)

    ②编译java文件成 .class文件

    ③使用jvm,把class文件通过类加载加载到内存中

    ④万事万物皆对象,class文件在内存中使用Class类表示

    ⑤当使用反射时候,首先需要获取Class类,得到了这个类之后,就可以得到class文件里面的所有内容;

    ⑥属性通过一个类Field

    ⑦构造方法通过一个类Constructor

    ⑧普通方法通过一个类Method

    二、使用反射操作类

    1、使用反射操作类里面的无参数的构造方法

      ①首先获取到Class类:

      //获取Class类

    Class class1 = Person.class;

    Class class2 = new Person().getClass();

    Class class3 = Class.forName("test07.Person"); 

      ②要对一个类进行实例化,可以new,不能new,如何获取?

    //得到Class
    Class c3 = Class.forName("test07.Person");
    //得到Person类的实例
    Person p = (Person) c3.newInstance();

    代码:

    //操作无参数的构造方法
        @Test
        public void test1() throws Exception {
            //得到Class
            Class c3 = Class.forName("test07.Person");
            //得到Person类的实例
            Person p = (Person) c3.newInstance();
            //设置值
            p.setName("zhansan");
            System.out.println(p.getName());
        }

    2、使用反射操作有参数的构造方法

    //操作有参数的构造方法
        @Test
        public void test2() throws Exception {
            Class c1 = Class.forName("test07.Person");
            //调用有参构造方法
            //c1.getConstructors();//获取所有的构造方法
            //传递是有参数的构造方法里面参数类型,类型使用class形式传递
            Constructor cs = c1.getConstructor(String.class,String.class);
            //通过有参数的构造方法设置值
            //通过有参数的构造方法创建Person实例
            Person p1 = (Person) cs.newInstance("lisi","100");
            System.out.println(p1.getId()+" "+p1.getName());
        }

    3、使用反射操作属性

        //操作name属性
        @Test
        public void test3() {
            try {
                //得到Class类
                Class c2 = Class.forName("test07.Person");
                //得到name属性
                //c2.getDeclaredFields();//表示得到所有的属性
                //得到Person类的实例
                Person p11 = (Person) c2.newInstance();
                //通过这个方法得到属性,参数是属性的名称
                Field f1 = c2.getDeclaredField("name");
                //操作的是私有的属性,则不让操作,需要设置可以操作私有属性setAccessible(true)
                f1.setAccessible(true);
                //设置name值,set方法。两个参数:第一个参数类的实例,第二个参数是设置的值
                f1.set(p11,"wangwu");//相当于p.name="wangwu";
                System.out.println(f1.get(p11));//相当于p.name
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    4、使用反射操作普通方法

      使用Method类表示普通方法 

        //操作普通方法,比如操作setName
        @Test
        public void test04() throws Exception {
            //得到Class类
            Class c4= Class.forName("test07.Person");
            //得到Person实例
            Person p4 = (Person) c4.newInstance();
            //得到普通方法
            //c4.getDeclaredMethods();//得到所有普通方法
            //传递两个参数:第一个参数,方法名称;第二个参数,通过方法里面参数的类型
            Method m1 = c4.getDeclaredMethod("setName", String.class);//让setName方法执行,执行设置值
            //使用invoke(p4,"niuqi"):传递两个参数,第一个参数,Person实例;第二个参数,设置的值
            //执行了invoke方法之后,相当于,执行了setName方法,同时通过这个方法设置了一个值niuqi
            m1.invoke(p4,"niuqi");
            System.out.println(p4.getName());
        }
    • 操作私有方法,需要设置值为true m1.setAccessible(true); 
    • 当操作的方法是静态的方法时候,因为静态方法调用方式是 类名.方法名,不需要类的实例
    • 使用反射操作静态方法时候,也不需要实例
    • 在invoke方法的第一个参数里面,写一个null, m1.invoke(null,"niuqi"); 

        

     
  • 相关阅读:
    阿里早期Android加固代码的实现分析
    如何利用C++的time头文件获取系统时间
    Python编写基于socket的非阻塞多人聊天室程序(单线程&多线程)
    Dalvik模式下在Android so库文件.init段、.init_array段构造函数上下断点
    手动绕过百度加固Debug.isDebuggerConnected反调试的方法
    request使用代理
    requests爬取豆瓣热门电视剧
    scrapy-继承默认的user-agent 中间件
    scrapy-下载器中间件 随机切换user_agent
    scrapy 直接在编辑器运行
  • 原文地址:https://www.cnblogs.com/gdwkong/p/7425586.html
Copyright © 2011-2022 走看看