• 反射


    时间:2016-11-5 21:59

    1、反射的原理
        反射应用在一些通用性比较高的代码中。
        绝大多数Java框架都是通过反射来实现的。
        在框架开发中,都是基于配置文件进行开发。
            在配置文件中配置了类之后,可以通过反射来得到类中的所有内容,可以执行类中的某个方法,不需要创建对象。

        类中的内容:
            无参构造
            有参构造
            成员属性

            成员方法

        分析反射原理:
            首先需要把Java文件保存到本地硬盘。
            编译java文件,生成.class字节码文件。
            使用JVM,把class文件通过类加载到内存中。
            class文件在内存中使用Class类表示。
            当使用反射的时候,首先需要获取到Class类,得到这个类的对象之后,就可以得到这个类的所有内容。
                包括构造方法、属性、普通方法。
            构造方法:Constructor
            属性:Filed
            普通方法:Method

    2、使用反射获取Class类对象

        //获取Class类
        Class p1 = Person.class;
        Class p2 = new Person().getClass();
        Class p3 = Class.forName("fanshe.Person");

        要对一个类进行实例化,如果不使用new,怎么获取?
            Person p = (Person) Class.forName("fanshe.Person").newInstance();
     

    3、操作有参数的构造方法:

        构造方法必须是public。

        //得到Class类对象
        Class c = Class.forName("fanshe.Person");
        //得到所有的构造方法(不常用)
        //c.getConstructors();
        //根据参数列表获取构造方法,传递的参数是参数类型的类
        Constructor cs = c.getConstructor(String.class, String.class);
        //此时已经获取到有参构造方法
        //使用有参构造方法创建对象
        Person p = (Person)cs.newInstance("张三","1");
        //获取Person属性
        System.out.println(p.getName());

    4、使用反射操作属性
        //得到Class类
        Class c = Class.forName("fanshe.Person");
        //得到Person类实例
        Person p = (Person) c.newInstance();    //需要执行强制类型转换
        //获取所有属性(不常用)
        //Field[] f = c.getDeclaredFields();
        //得到name属性
        Field name = c.getDeclaredField("name");
        //将私有属性设置为可访问(私有属性默认为false,不允许操作)
        name.setAccessible(true);
        //设置name值
        name.set(p, "王五");//相当于p.name = "王五",第一个参数是实例对象,第二个参数是赋值的值
        //获取name值
        System.out.println(name.get(p));//相当于p.name,传递的参数是实例对象

    /***************************************************************************/
    getDeclaredField是可以获取一个类的所有字段. 
    getField只能获取类的public 字段
    /***************************************************************************/ 

    5、使用泛型操作普通方法
        使用Method类表示普通方法。(setName)

        //得到Class类
        Class c = Class.forName("fanshe.Person");
        //获取Person实例
        Person p = (Person)c.newInstance();
        //得到所有的普通方法(不常用)
        //c.getDeclaredMethods();
        //得到setName(),第一个参数是方法名,第二个参数是参数类型的类
        Method m = c.getDeclaredMethod("setName", String.class);
        //如果操作的是私有方法,需要将访问权限设置为true
        m.setAccessible(true); 
        //执行Method方法
        m.invoke(p, "赵六");    //第一个参数是实例对象,第二个参数是方法参数
        //获取getName()
        Method g = c.getDeclaredMethod("getName");
        //执行getName方法
        System.out.println(g.invoke(p));

        当操作的方法是静态方法的时候,就不需要创建实例了,可以直接通过类名来调用。
        当使用反射操作静态方法的时候,也不需要实例对象:
            m.invoke(null, "哈哈");
        参数为null,表示这是一个静态方法。

    6、方法总结
        Class  forName(String  ClassURL)
            获取类对象。
        Constructor  getConstructor(Object...)
            获取构造方法。
        Object  newInstance(Object...)
            创建实例对象。
        Field  getDeclaredField(String FieldName)
            根据名称获取属性。
        void  setAccessiable(boolean  flag)
            设置私有属性是否可以访问。
        void  set(Object obj, Object value...)
            执行指定实例对象的方法。
                obj:实例对象
                value:方法参数
        void  get(Object obj)
            执行指定实例对象的方法。
        Method  getDeclaredMethod(String methodName, Class argsClass...)
            根据方法名和参数列表获取方法。
        void  invoke(Object obj, Object value...)
            执行指定实例的方法,并传递参数列表。
  • 相关阅读:
    $(document).Ready()方法 VS OnLoad事件 VS $(window).load()方法
    ASP.NET MVC之文件上传【二】
    ASP.NET MVC之文件上传【一】
    [JSOI2009]球队收益
    Codeforces 323 B Tournament-graph
    2017 [六省联考] T6 寿司餐厅
    [CQOI2014]数三角形
    Hdoj 3506 Monkey Party
    Loj #125. 除数函数求和(2)
    Codeforces 235 E Number Challenge
  • 原文地址:https://www.cnblogs.com/wwwwyc/p/6375236.html
Copyright © 2020-2023  润新知